BluetoothTest.Mod 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. MODULE BluetoothTest; (** AUTHOR "mt"; PURPOSE "Testing BluetoothHCI"; *)
  2. IMPORT
  3. SYSTEM, KernelLog, Commands, Streams, Modules, Serials, Plugins, Usb, Bluetooth, BluetoothUSB,
  4. HCI := BluetoothHCI, L2CAP := BluetoothL2CAP, Strings;
  5. TYPE
  6. Ident = ARRAY 32 OF CHAR;
  7. Device = OBJECT
  8. VAR
  9. next: Device;
  10. ident: Ident;
  11. port: Serials.Port;
  12. tl: Bluetooth.TransportLayer;
  13. hci: HCI.HCI;
  14. l2cap: L2CAP.L2CAP;
  15. PROCEDURE HCIEnumerator(l: HCI.Link; par: ANY): BOOLEAN;
  16. VAR i: LONGINT;
  17. BEGIN
  18. KernelLog.String(" connection to "); FOR i := 0 TO Bluetooth.BDAddrLen-1 DO KernelLog.Hex(ORD(l.remote[i]), -2) END;
  19. KernelLog.String("; handle "); KernelLog.Int(l.handle, 0); KernelLog.Ln;
  20. RETURN TRUE
  21. END HCIEnumerator;
  22. PROCEDURE ListHCIConnections;
  23. BEGIN
  24. KernelLog.String("Device '"); KernelLog.String(ident); KernelLog.String("': active connections:"); KernelLog.Ln;
  25. hci.EnumerateLinks(HCIEnumerator, NIL);
  26. KernelLog.String("done."); KernelLog.Ln
  27. END ListHCIConnections;
  28. PROCEDURE InitL2CAP;
  29. VAR res: WORD;
  30. BEGIN
  31. IF (l2cap # NIL) THEN CloseL2CAP END;
  32. (* NEW(l2cap, hci, res); *)
  33. NEW(l2cap);
  34. IF (res = 0) THEN
  35. l2cap.EventIndication(L2CAP.EConnectInd, ConnectIndication, res); ASSERT(res = 0);
  36. l2cap.EventIndication(L2CAP.EConfigInd, ConfigIndication, res); ASSERT(res= 0);
  37. l2cap.EventIndication(L2CAP.EDisconnectInd, DisconnectIndication, res); ASSERT(res = 0);
  38. l2cap.EventIndication(L2CAP.EQoSViolationInd, QoSViolationIndication, res); ASSERT(res = 0);
  39. KernelLog.String("L2CAP initialized")
  40. ELSE l2cap := NIL; KernelLog.String("failed to initialize L2CAP: res = "); KernelLog.Int(res, 0)
  41. END
  42. END InitL2CAP;
  43. PROCEDURE CloseL2CAP;
  44. BEGIN
  45. IF (l2cap # NIL) THEN l2cap := NIL; KernelLog.String("L2CAP closed")
  46. ELSE KernelLog.String("L2CAP not available")
  47. END
  48. END CloseL2CAP;
  49. PROCEDURE ConnectIndication(indication: L2CAP.Indication);
  50. VAR res: WORD;
  51. BEGIN
  52. KernelLog.String(ident); KernelLog.String(": connect indication!!!"); KernelLog.Ln;
  53. WITH indication: L2CAP.ConnectInd DO
  54. l2cap.ConnectResponse(indication.bdAddr, indication.ident, indication.c.sid, 0, 0, res);
  55. IF (res # 0) THEN KernelLog.String("cannot send connection response!"); KernelLog.Ln END
  56. END
  57. END ConnectIndication;
  58. PROCEDURE ConfigIndication(indication: L2CAP.Indication);
  59. VAR res: WORD;
  60. BEGIN
  61. WITH indication: L2CAP.ConfigInd DO
  62. KernelLog.String(ident); KernelLog.String(": configuration indication:"); KernelLog.Ln;
  63. KernelLog.String(" outMTU: "); KernelLog.Int(indication.outMTU, 0); KernelLog.Ln;
  64. KernelLog.String(" inFlow: "); KernelLog.Int(indication.inFlow, 0); KernelLog.Ln;
  65. KernelLog.String(" inFlushTO: "); KernelLog.Int(indication.inFlushTO, 0); KernelLog.Ln;
  66. l2cap.ConfigurationResponse(indication.c.sid, indication.ident, 0, 0, res);
  67. IF (res # 0) THEN KernelLog.String("cannot send configuration response!"); KernelLog.Ln END
  68. END
  69. END ConfigIndication;
  70. PROCEDURE DisconnectIndication(indication: L2CAP.Indication);
  71. BEGIN
  72. KernelLog.String(ident); KernelLog.String(": disconnect indication!!!"); KernelLog.Ln
  73. END DisconnectIndication;
  74. PROCEDURE QoSViolationIndication(indication: L2CAP.Indication);
  75. BEGIN
  76. KernelLog.String(ident); KernelLog.String(": QoS violation indication!!!"); KernelLog.Ln
  77. END QoSViolationIndication;
  78. PROCEDURE SendString(cid: LONGINT; VAR str: ARRAY OF CHAR);
  79. VAR buf: POINTER TO ARRAY OF CHAR; i, len, res: LONGINT;
  80. BEGIN
  81. NEW(buf,LEN(str)+2);
  82. WHILE (str[i] # 0X) DO buf[i] := str[i]; INC(i) END;
  83. buf[i] := 0AX; INC(i);
  84. l2cap.Write(cid, 0, i, buf^ ,len, res);
  85. IF (len # i) THEN KernelLog.String("Warning: cannot send all data"); KernelLog.Ln
  86. ELSIF (res # 0) THEN KernelLog.String("Warning: cannot send (res = "); KernelLog.Int(res, 0); KernelLog.Char(")"); KernelLog.Ln
  87. END
  88. END SendString;
  89. PROCEDURE Poll(cid: LONGINT; size: INTEGER; VAR off: INTEGER; VAR data: ARRAY OF CHAR);
  90. VAR buf: ARRAY 256 OF CHAR; i, res, len: LONGINT;
  91. BEGIN
  92. REPEAT
  93. l2cap.Read(cid, LEN(buf), buf, res, len);
  94. IF (res = 0) THEN
  95. FOR i := 0 TO len-1 DO KernelLog.Char(buf[i]) END
  96. END
  97. UNTIL (res # 0)
  98. END Poll;
  99. PROCEDURE PollBytes(cid: LONGINT; size: INTEGER; VAR off: INTEGER; VAR data: ARRAY OF CHAR);
  100. VAR buf: ARRAY 256 OF CHAR; i, res, len: LONGINT;
  101. BEGIN
  102. REPEAT
  103. l2cap.Read(cid, LEN(buf), buf, res, len);
  104. KernelLog.Char("[");
  105. IF (res = 0) THEN
  106. FOR i := 0 TO len-1 DO KernelLog.Hex(ORD(buf[i]), -2); KernelLog.Char(" ") END
  107. END;
  108. KernelLog.Char("]")
  109. UNTIL (res # 0)
  110. END PollBytes;
  111. END Device;
  112. VAR
  113. devices: Device;
  114. PROCEDURE Add(d: Device);
  115. BEGIN
  116. d.next := devices.next; devices.next := d
  117. END Add;
  118. PROCEDURE Remove(d: Device);
  119. VAR p,q: Device;
  120. BEGIN
  121. p := devices.next; q := devices;
  122. WHILE (p # NIL) & (p # d) DO q := p; p := p.next END;
  123. IF (p # NIL) THEN q.next := p.next END
  124. END Remove;
  125. PROCEDURE Find(ident: ARRAY OF CHAR): Device;
  126. VAR p: Device;
  127. BEGIN
  128. p := devices.next;
  129. WHILE (p # NIL) & (p.ident # ident) DO p := p.next END;
  130. RETURN p
  131. END Find;
  132. (* For USB *)
  133. PROCEDURE Open*(context : Commands.Context);
  134. VAR
  135. device : Device;
  136. tl : BluetoothUSB.UsbTransportLayer; devicename, ident : Ident; plugin : Plugins.Plugin;
  137. BEGIN {EXCLUSIVE}
  138. IF context.arg.GetString(devicename) & context.arg.GetString(ident) THEN
  139. plugin := Usb.usbDrivers.Get(devicename);
  140. IF (plugin # NIL) THEN
  141. IF (Find(ident) = NIL) THEN
  142. NEW(device); device.ident := ident;
  143. NEW(tl, devicename, NIL, NIL); device.tl := tl;
  144. NEW(device.hci, tl);
  145. device.hci.OnInquiry := InquiryResult;
  146. (*
  147. d.hci.OnReceiveACLData := ReceiveData;
  148. *)
  149. Add(device);
  150. context.out.String("Device '"); context.out.String(ident); context.out.String("' on ");
  151. context.out.String(devicename); context.out.String(" connected.");
  152. context.out.Ln;
  153. ELSE
  154. context.error.String("Device '"); context.error.String(ident); context.error.String("' already present.");
  155. context.error.Ln;
  156. END;
  157. ELSE
  158. context.error.String("Bluetooth USB device '"); context.error.String(devicename);
  159. context.error.String("' not found."); context.error.Ln;
  160. END;
  161. ELSE
  162. context.error.String("Expected <UsbDeviceName> <DeviceName> parameters."); context.error.Ln;
  163. END;
  164. END Open;
  165. (* For UART
  166. PROCEDURE Open*(context : Commands.Context);
  167. VAR
  168. ident: Ident; d: Device;
  169. portNo, bps, data, parity, stop, res: LONGINT;
  170. tl: BluetoothUART.TransportLayer;
  171. BEGIN
  172. context.arg.GetString(ident);
  173. context.arg.GetInteger(portNo, FALSE);
  174. context.arg.GetInteger(bps, FALSE);
  175. context.arg.GetInteger(data, FALSE);
  176. context.arg.GetInteger(parity, FALSE);
  177. context.arg.GetInteger(stop, FALSE);
  178. IF (context.arg.res = Streams.Ok) THEN
  179. IF Find(ident) = NIL THEN
  180. NEW(d); d.ident := ident;
  181. NEW(d.port, portNo-1, bps, data, parity, stop, res);
  182. IF (res = 0) THEN
  183. NEW(d.tl, ident, d.port.Send, d.port.Receive);
  184. NEW(d.hci, d.tl);
  185. d.hci.OnInquiry := InquiryResult;
  186. (*
  187. d.hci.OnReceiveACLData := ReceiveData;
  188. *)
  189. Add(d);
  190. context.out.String("Device '"); context.out.String(ident); context.out.String("' ready.");
  191. context.out.Ln;
  192. ELSE
  193. context.error.String("Cannot open com port."); context.error.Ln;
  194. END
  195. ELSE context.out.String("Device '"); context.out.String(ident); context.out.String("' already present.")
  196. END
  197. ELSE context.out.String("Syntax error.")
  198. END;
  199. context.out.Ln;
  200. END Open;
  201. *)
  202. PROCEDURE Close*(context : Commands.Context);
  203. VAR ident: Ident; d: Device;
  204. BEGIN
  205. IF context.arg.GetString(ident) THEN
  206. d := Find(ident);
  207. IF (d # NIL) THEN
  208. d.hci.Close;
  209. d.port.Close;
  210. Remove(d);
  211. context.out.String("Device '"); context.out.String(ident); context.out.String("' removed."); context.out.Ln;
  212. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  213. END
  214. ELSE context.out.String("Syntax error.")
  215. END;
  216. context.out.Ln;
  217. END Close;
  218. PROCEDURE TraceMode*(context : Commands.Context);
  219. VAR ident: Ident; c: CHAR; d: Device;
  220. BEGIN
  221. IF context.arg.GetString(ident) & context.arg.GetChar(c) THEN
  222. d := Find(ident);
  223. IF (d # NIL) THEN
  224. c := CAP(c);
  225. (* d.tl.TraceSend := (c="T") OR (c="B");
  226. d.tl.TraceReceive := (c="R") OR (c="B");
  227. context.out.String("Device '"); context.out.String(ident); context.out.String("': tracing mode = ");
  228. IF d.tl.TraceSend THEN context.out.Char("T") END;
  229. IF d.tl.TraceReceive THEN context.out.Char("R") END; *)
  230. context.out.Ln;
  231. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  232. END
  233. ELSE context.out.String("Syntax error.")
  234. END;
  235. context.out.Ln;
  236. END TraceMode;
  237. PROCEDURE ReadLocalName*(context : Commands.Context);
  238. VAR
  239. ident: Ident; d: Device;
  240. event: Bluetooth.EventPacket; pending: BOOLEAN; res, i: LONGINT;
  241. BEGIN
  242. IF context.arg.GetString(ident) THEN
  243. d := Find(ident);
  244. IF (d # NIL) THEN
  245. context.out.String("Reading local name..."); context.out.Ln;
  246. d.hci.SendCommand(HCI.ogfControl, HCI.ocfReadLocalName, "", 0, event, pending, res);
  247. IF (res = 0) & ~pending THEN
  248. context.out.String(" success: '");
  249. i := 0;
  250. WHILE (i < 248) & (event.params[4+i] # 0X) DO
  251. context.out.Char(event.params[4+i]);
  252. INC(i)
  253. END;
  254. context.out.Char("'"); context.out.Ln;
  255. ELSE
  256. context.out.String(" failed; res = "); context.out.Int(res, 0); context.out.Ln;
  257. END
  258. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  259. END
  260. ELSE context.out.String("Syntax error.")
  261. END;
  262. context.out.Ln;
  263. END ReadLocalName;
  264. PROCEDURE ChangeLocalName*(context : Commands.Context);
  265. VAR
  266. ident: Ident; d: Device;
  267. name: ARRAY 248 OF CHAR; event: Bluetooth.EventPacket; pending: BOOLEAN; res : WORD;
  268. BEGIN
  269. IF context.arg.GetString(ident) & context.arg.GetString(name) THEN
  270. d := Find(ident);
  271. IF (d # NIL) THEN
  272. context.out.String("Changing local name to '"); context.out.String(name); context.out.String("'..."); context.out.Ln;
  273. d.hci.SendCommand(HCI.ogfControl, HCI.ocfChangeLocalName, name, 248, event, pending, res);
  274. IF (res = 0) & ~pending THEN
  275. context.out.String(" success")
  276. ELSE
  277. context.out.String(" failed; res = "); context.out.Int(res, 0)
  278. END;
  279. context.out.Ln;
  280. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  281. END
  282. ELSE context.out.String("Syntax error.")
  283. END;
  284. context.out.Ln;
  285. END ChangeLocalName;
  286. PROCEDURE ReadClassOfDevice*(context : Commands.Context);
  287. VAR
  288. ident: Ident; d: Device;
  289. event: Bluetooth.EventPacket; pending: BOOLEAN; res, i: LONGINT;
  290. BEGIN
  291. IF context.arg.GetString(ident) THEN
  292. d := Find(ident);
  293. IF (d # NIL) THEN
  294. context.out.String("Reading class of device..."); context.out.Ln;
  295. d.hci.SendCommand(HCI.ogfControl, HCI.ocfReadClassOfDevice, "", 0, event, pending, res);
  296. IF (res = 0) & ~pending THEN
  297. context.out.String(" success; class of device = ");
  298. FOR i := 0 TO Bluetooth.DeviceClassLen-1 DO
  299. context.out.Hex(ORD(event.params[4+i]), -2); context.out.Char(" ")
  300. END
  301. ELSE context.out.String(" failed; res = "); context.out.Int(res, 0)
  302. END
  303. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  304. END
  305. ELSE context.out.String("Syntax error.")
  306. END;
  307. context.out.Ln;
  308. END ReadClassOfDevice;
  309. PROCEDURE WriteClassOfDevice*(context : Commands.Context);
  310. VAR
  311. ident: Ident; d: Device;
  312. event: Bluetooth.EventPacket; pending: BOOLEAN; res, i: LONGINT; cod: Bluetooth.DeviceClass;
  313. BEGIN
  314. context.arg.SkipWhitespace; context.arg.String(ident); context.arg.SkipWhitespace;
  315. FOR i := 0 TO LEN(cod)-1 DO cod[i] := HexToChar(context.arg.Get(), context.arg.Get()) END;
  316. IF (context.arg.res = Streams.Ok) THEN
  317. d := Find(ident);
  318. IF (d # NIL) THEN
  319. context.out.String("Writing class of device..."); context.out.Ln;
  320. d.hci.SendCommand(HCI.ogfControl, HCI.ocfWriteClassOfDevice, cod, 3, event, pending, res);
  321. IF (res = 0) & ~pending THEN context.out.String(" success")
  322. ELSE context.out.String(" failed; res = "); context.out.Int(res, 0)
  323. END
  324. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  325. END
  326. ELSE context.out.String("Syntax error.")
  327. END;
  328. context.out.Ln;
  329. END WriteClassOfDevice;
  330. PROCEDURE Reset*(context : Commands.Context);
  331. VAR ident: Ident; d: Device; res: WORD;
  332. BEGIN
  333. IF context.arg.GetString(ident) THEN
  334. d := Find(ident);
  335. IF (d # NIL) THEN
  336. context.out.String("Sending reset...");
  337. res := d.hci.Reset();
  338. context.out.String("res = "); context.out.Int(res, 0)
  339. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  340. END
  341. ELSE context.out.String("Syntax error.")
  342. END;
  343. context.out.Ln;
  344. END Reset;
  345. PROCEDURE ReadScanEnable*(context : Commands.Context);
  346. VAR
  347. ident: Ident; d: Device;
  348. res: WORD; event: Bluetooth.EventPacket; pending: BOOLEAN;
  349. BEGIN
  350. IF context.arg.GetString(ident) THEN
  351. d := Find(ident);
  352. IF (d # NIL) THEN
  353. context.out.String("Reading scan mode...");
  354. d.hci.SendCommand(HCI.ogfControl, HCI.ocfReadScanEnable, "", 0, event, pending, res);
  355. IF (res = 0) THEN
  356. context.out.String("ok"); context.out.Ln;
  357. CASE ORD(event.params[4]) OF
  358. | 0: context.out.String(" no scans enabled")
  359. | 1: context.out.String(" inquiry scan enabled, page scan disabled")
  360. | 2: context.out.String(" inquiry scan disabled, page scan enabled")
  361. | 3: context.out.String(" inquiry scan enabled, page scan enabled")
  362. ELSE context.out.String(" invalid code: "); context.out.Int(ORD(event.params[4]), 0)
  363. END
  364. ELSE context.out.String("error, res = "); context.out.Int(res, 0)
  365. END
  366. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  367. END
  368. ELSE context.out.String("Syntax error.")
  369. END;
  370. context.out.Ln;
  371. END ReadScanEnable;
  372. PROCEDURE WriteScanEnable*(context : Commands.Context);
  373. VAR
  374. ident: Ident; d: Device;
  375. res, scanMode: LONGINT; param: ARRAY 1 OF CHAR; event: Bluetooth.EventPacket; pending: BOOLEAN;
  376. BEGIN
  377. IF context.arg.GetString(ident) & context.arg.GetInteger(scanMode, TRUE) THEN
  378. IF (0 <= scanMode) & (scanMode <= 3) THEN
  379. d := Find(ident);
  380. IF (d # NIL) THEN
  381. context.out.String("Sending write scan enable...");
  382. param[0] := CHR(scanMode);
  383. d.hci.SendCommand(HCI.ogfControl, HCI.ocfWriteScanEnable, param, 1, event, pending, res);
  384. context.out.String("res = "); context.out.Int(res, 0)
  385. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  386. END
  387. ELSE context.out.String("Invalid parameters")
  388. END
  389. ELSE context.out.String("Syntax error.")
  390. END;
  391. context.out.Ln;
  392. END WriteScanEnable;
  393. PROCEDURE SetFilter*(context : Commands.Context);
  394. VAR
  395. ident: Ident; d: Device;
  396. cond: ARRAY 1 OF CHAR; res: WORD;
  397. BEGIN
  398. IF context.arg.GetString(ident) THEN
  399. d := Find(ident);
  400. IF (d # NIL) THEN
  401. context.out.String("Sending SetEventFilter...");
  402. cond[0] := HCI.EFCSAAOn;
  403. res := d.hci.SetEventFilter(HCI.EFConnectionSetup, HCI.EFCSAll, cond);
  404. context.out.String("res = "); context.out.Int(res, 0)
  405. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  406. END
  407. ELSE context.out.String("Syntax error.")
  408. END;
  409. context.out.Ln;
  410. END SetFilter;
  411. PROCEDURE ReadPageScanActivity*(context : Commands.Context);
  412. VAR
  413. ident: Ident; d: Device;
  414. interval, window, res: LONGINT; pending: BOOLEAN; event: Bluetooth.EventPacket; intStr, winStr: ARRAY 16 OF CHAR;
  415. BEGIN
  416. IF context.arg.GetString(ident) THEN
  417. d := Find(ident);
  418. IF (d # NIL) THEN
  419. context.out.String("Reading page scan activity...");
  420. d.hci.SendCommand(HCI.ogfControl, HCI.ocfReadPageScanActivity, "", 0, event, pending, res);
  421. context.out.String("done."); context.out.Ln;
  422. IF (res = 0) THEN
  423. interval := ORD(event.params[4])+LONG(ORD(event.params[5]))*100H;
  424. window := ORD(event.params[6])+LONG(ORD(event.params[7]))*100H;
  425. Strings.FloatToStr(interval*0.625, 6, 2, 0, intStr);
  426. Strings.FloatToStr(window*0.625, 6, 2, 0, winStr);
  427. context.out.String(" interval: "); context.out.Int(interval, 0); context.out.String("*0.625ms = "); context.out.String(intStr); context.out.String("ms"); context.out.Ln;
  428. context.out.String(" window: "); context.out.Int(window, 0); context.out.String("*0.625ms = "); context.out.String(winStr); context.out.String("ms"); context.out.Ln
  429. ELSE
  430. context.out.String(" Error: res = "); context.out.Int(res, 0)
  431. END
  432. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  433. END
  434. ELSE context.out.String("Syntax error.")
  435. END;
  436. context.out.Ln;
  437. END ReadPageScanActivity;
  438. PROCEDURE WritePageScanActivity*(context : Commands.Context);
  439. VAR
  440. ident: Ident; d: Device;
  441. interval, window, res: LONGINT; pending: BOOLEAN; event: Bluetooth.EventPacket; param: ARRAY 4 OF CHAR;
  442. BEGIN
  443. IF context.arg.GetString(ident) & context.arg.GetInteger(interval, TRUE) & context.arg.GetInteger(window, TRUE) THEN
  444. d := Find(ident);
  445. IF (d # NIL) THEN
  446. IF (12H <= interval) & (interval <= 1000H) & (12H <= window) & (window <= 1000H) THEN
  447. context.out.String("Writing page scan activity...");
  448. param[0] := CHR(interval MOD 100H); param[1] := CHR(interval DIV 100H);
  449. param[2] := CHR(window MOD 100H); param[3] := CHR(window DIV 100H);
  450. d.hci.SendCommand(HCI.ogfControl, HCI.ocfWritePageScanActivity, param, 4, event, pending, res);
  451. context.out.String("done."); context.out.Ln;
  452. IF (res = 0) THEN
  453. ELSE
  454. context.out.String(" Error: res = "); context.out.Int(res, 0)
  455. END
  456. ELSE
  457. context.out.String("Invalid parameters. Values range from 0012H to 1000H")
  458. END
  459. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  460. END
  461. ELSE context.out.String("Syntax error.")
  462. END;
  463. context.out.Ln;
  464. END WritePageScanActivity;
  465. PROCEDURE ReadInquiryScanActivity*(context : Commands.Context);
  466. VAR
  467. ident: Ident; d: Device;
  468. interval, window, res: LONGINT; pending: BOOLEAN; event: Bluetooth.EventPacket; intStr, winStr: ARRAY 16 OF CHAR;
  469. BEGIN
  470. IF context.arg.GetString(ident) THEN
  471. d := Find(ident);
  472. IF (d # NIL) THEN
  473. context.out.String("Reading inquiry scan activity...");
  474. d.hci.SendCommand(HCI.ogfControl, HCI.ocfReadInquiryScanActivity, "", 0, event, pending, res);
  475. context.out.String("done."); context.out.Ln;
  476. IF (res = 0) THEN
  477. interval := ORD(event.params[4])+LONG(ORD(event.params[5]))*100H;
  478. window := ORD(event.params[6])+LONG(ORD(event.params[7]))*100H;
  479. Strings.FloatToStr(interval*0.625, 6, 2, 0, intStr);
  480. Strings.FloatToStr(window*0.625, 6, 2, 0, winStr);
  481. context.out.String(" interval: "); context.out.Int(interval, 0); context.out.String("*0.625ms = "); context.out.String(intStr); context.out.String("ms"); context.out.Ln;
  482. context.out.String(" window: "); context.out.Int(window, 0); context.out.String("*0.625ms = "); context.out.String(winStr); context.out.String("ms"); context.out.Ln
  483. ELSE
  484. context.out.String(" Error: res = "); context.out.Int(res, 0)
  485. END
  486. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  487. END
  488. ELSE context.out.String("Syntax error.")
  489. END;
  490. context.out.Ln;
  491. END ReadInquiryScanActivity;
  492. PROCEDURE WriteInquiryScanActivity*(context : Commands.Context);
  493. VAR
  494. ident: Ident; d: Device;
  495. interval, window, res: LONGINT; pending: BOOLEAN; event: Bluetooth.EventPacket; param: ARRAY 4 OF CHAR;
  496. BEGIN
  497. IF context.arg.GetString(ident) & context.arg.GetInteger(interval, TRUE) & context.arg.GetInteger(window, TRUE) THEN
  498. d := Find(ident);
  499. IF (d # NIL) THEN
  500. IF (12H <= interval) & (interval <= 1000H) & (12H <= window) & (window <= 1000H) THEN
  501. context.out.String("Writing inquiry scan activity...");
  502. param[0] := CHR(interval MOD 100H); param[1] := CHR(interval DIV 100H);
  503. param[2] := CHR(window MOD 100H); param[3] := CHR(window DIV 100H);
  504. d.hci.SendCommand(HCI.ogfControl, HCI.ocfWriteInquiryScanActivity, param, 4, event, pending, res);
  505. context.out.String("done."); context.out.Ln;
  506. IF (res = 0) THEN
  507. ELSE
  508. context.out.String(" Error: res = "); context.out.Int(res, 0)
  509. END
  510. ELSE
  511. context.out.String("Invalid parameters. Values range from 0012H to 1000H")
  512. END
  513. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  514. END
  515. ELSE context.out.String("Syntax error.")
  516. END;
  517. context.out.Ln;
  518. END WriteInquiryScanActivity;
  519. PROCEDURE Inquiry*(context : Commands.Context);
  520. VAR
  521. ident: Ident; d: Device; lap: ARRAY 3 OF CHAR;
  522. params: ARRAY 5 OF CHAR; event: Bluetooth.EventPacket; pending: BOOLEAN;
  523. length, numResponses, i, res: LONGINT;
  524. BEGIN
  525. context.arg.SkipWhitespace; context.arg.String(ident); context.arg.SkipWhitespace;
  526. FOR i := 0 TO LEN(lap)-1 DO lap[i] := HexToChar(context.arg.Get(), context.arg.Get()) END;
  527. context.arg.SkipWhitespace; context.arg.Int(length, TRUE);
  528. context.arg.SkipWhitespace; context.arg.Int(numResponses, TRUE);
  529. IF (context.arg.res = Streams.Ok) THEN
  530. IF (0 < length) & (length <= 30H) & (0 <= numResponses) & (numResponses < 100H) THEN
  531. d := Find(ident);
  532. IF (d # NIL) THEN
  533. context.out.String("Sending inquiry command..."); context.out.Ln;
  534. params[0] := lap[2]; params[1] := lap[1]; params[2] := lap[0];
  535. params[3] := CHR(length); params[4] := CHR(numResponses);
  536. d.hci.SendCommand(HCI.ogfLinkControl, HCI.ocfInquiry, params, 5, event, pending, res);
  537. IF (res = 0) THEN context.out.String(" inquiry process started")
  538. ELSE context.out.String(" failed")
  539. END
  540. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  541. END
  542. ELSE context.out.String("Wrong parameters.")
  543. END
  544. ELSE context.out.String("Syntax error.")
  545. END;
  546. context.out.Ln;
  547. END Inquiry;
  548. PROCEDURE InquiryResult(sender: HCI.HCI; bdAddr: Bluetooth.BDAddr; deviceClass: Bluetooth.DeviceClass;
  549. psRepMode, psPeriodMode, psMode, clockOffset: LONGINT);
  550. VAR k: LONGINT;
  551. BEGIN
  552. KernelLog.Enter;
  553. KernelLog.String("Inquiry Result: "); KernelLog.Ln;
  554. KernelLog.String(" remote: ");
  555. FOR k := 0 TO Bluetooth.BDAddrLen-1 DO KernelLog.Hex(ORD(bdAddr[k]), -2); KernelLog.Char(" ") END;
  556. KernelLog.Ln;
  557. KernelLog.String(" class of device: ");
  558. FOR k := 0 TO Bluetooth.DeviceClassLen-1 DO KernelLog.Hex(ORD(deviceClass[k]), -2); KernelLog.Char(" "); END;
  559. KernelLog.Ln;
  560. KernelLog.String(" page scan repetition mode: "); KernelLog.Int(psRepMode, 0); KernelLog.Ln;
  561. KernelLog.String(" page scan period mode: "); KernelLog.Int(psPeriodMode, 0); KernelLog.Ln;
  562. KernelLog.String(" page scan mode: "); KernelLog.Int(psMode, 0); KernelLog.Ln;
  563. KernelLog.String(" clock offset: "); KernelLog.Int(clockOffset, 0);
  564. KernelLog.Exit
  565. END InquiryResult;
  566. PROCEDURE Val(ch: CHAR): LONGINT;
  567. BEGIN
  568. IF ("0" <= ch) & (ch <= "9") THEN RETURN ORD(ch) - ORD("0")
  569. ELSIF ("A" <= ch) & (ch <= "F") THEN RETURN ORD(ch) - ORD("A")+10
  570. ELSIF ("a" <= ch) & (ch <= "f") THEN RETURN ORD(ch) - ORD("a")+10
  571. ELSE RETURN -1
  572. END
  573. END Val;
  574. PROCEDURE HexToChar(v1, v2: CHAR): CHAR;
  575. VAR val1, val2: LONGINT;
  576. BEGIN
  577. val1 := Val(v1); val2 := Val(v2);
  578. IF (val1 # -1) & (val2 # -1) THEN RETURN CHR(val1*10H+val2)
  579. ELSE RETURN 0X
  580. END
  581. END HexToChar;
  582. PROCEDURE ConnectTo*(context : Commands.Context);
  583. VAR
  584. ident: Ident; d: Device;
  585. remote: Bluetooth.BDAddr; i , offset, res: LONGINT;
  586. BEGIN
  587. context.arg.SkipWhitespace; context.arg.String(ident); context.arg.SkipWhitespace;
  588. FOR i := 0 TO LEN(remote)-1 DO remote[i] := HexToChar(context.arg.Get(), context.arg.Get()) END;
  589. context.arg.SkipWhitespace; context.arg.Int(offset, TRUE);
  590. IF (context.arg.res = Streams.Ok) THEN
  591. d := Find(ident);
  592. IF (d # NIL) THEN
  593. context.out.String("Connecting to "); FOR i := 0 TO LEN(remote)-1 DO context.out.Hex(ORD(remote[i]), -2) END; context.out.String("...");
  594. res := d.hci.CreateConnection(remote, offset);
  595. IF (res = 0) THEN context.out.String("success.")
  596. ELSE context.out.String("failed; error code = "); context.out.Hex(res, -2)
  597. END
  598. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  599. END
  600. ELSE context.out.String("Syntax error.")
  601. END;
  602. context.out.Ln;
  603. END ConnectTo;
  604. PROCEDURE Supported(out : Streams.Writer; feature: ARRAY OF CHAR; s: SET; bit: LONGINT);
  605. BEGIN
  606. out.String(" "); out.String(feature); out.String(": ");
  607. IF (bit IN s) THEN out.String("yes") ELSE out.String("no") END;
  608. out.Ln
  609. END Supported;
  610. PROCEDURE ReadLocalSupportedFeatures*(context : Commands.Context);
  611. VAR
  612. ident: Ident; d: Device;
  613. res: WORD; event: Bluetooth.EventPacket; pending: BOOLEAN;
  614. s: SET;
  615. BEGIN
  616. IF context.arg.GetString(ident) THEN
  617. d := Find(ident);
  618. IF (d # NIL) THEN
  619. context.out.String("Reading local supported features... ");
  620. d.hci.SendCommand(HCI.ogfInformational, HCI.ocfReadLocalSupportedFeatures, "", 0, event, pending, res);
  621. IF (res = 0) THEN
  622. context.out.String("success."); context.out.Ln;
  623. (* byte 0 *)
  624. s := SYSTEM.VAL(SET, event.params[4]);
  625. Supported(context.out, "3-slot packets", s, 0);
  626. Supported(context.out, "5-slot packets", s, 1);
  627. Supported(context.out, "encryption", s, 2);
  628. Supported(context.out, "slot offset", s, 3);
  629. Supported(context.out, "timing accuracy", s, 4);
  630. Supported(context.out, "switch", s, 5);
  631. Supported(context.out, "hold mode", s, 6);
  632. Supported(context.out, "sniff mode", s, 7);
  633. (* byte 1 *)
  634. s := SYSTEM.VAL(SET, event.params[5]);
  635. Supported(context.out, "park mode", s, 0);
  636. Supported(context.out, "RSSI", s, 1);
  637. Supported(context.out, "channel quality driven data rate", s, 2);
  638. Supported(context.out, "SCO link", s, 3);
  639. Supported(context.out, "HV2 packets", s, 4);
  640. Supported(context.out, "HV3 packets", s, 5);
  641. Supported(context.out, "u-law log", s, 6);
  642. Supported(context.out, "A-law log", s, 7);
  643. (* byte 2 *)
  644. s := SYSTEM.VAL(SET, event.params[6]);
  645. Supported(context.out, "CVSD", s, 0);
  646. Supported(context.out, "paging scheme", s, 2);
  647. Supported(context.out, "power control", s, 3);
  648. context.out.String(" transparent SCO data: "); context.out.Int(ORD(event.params[6]) DIV 10H, 0); context.out.Ln;
  649. context.out.Ln;
  650. ELSE context.out.String("failed; error code = "); context.out.Hex(res, -2)
  651. END
  652. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  653. END
  654. ELSE context.out.String("Syntax error.")
  655. END;
  656. context.out.Ln;
  657. END ReadLocalSupportedFeatures;
  658. PROCEDURE ListHCIConnections*(context : Commands.Context);
  659. VAR ident: Ident; d: Device;
  660. BEGIN
  661. IF (context.arg.res = Streams.Ok) THEN
  662. d := Find(ident);
  663. IF (d # NIL) THEN
  664. d.ListHCIConnections
  665. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  666. END
  667. ELSE context.out.String("Syntax error.")
  668. END;
  669. context.out.Ln;
  670. END ListHCIConnections;
  671. PROCEDURE ReadClockOffset*(context : Commands.Context);
  672. VAR
  673. ident: Ident; d: Device;
  674. handle, res: LONGINT; event: Bluetooth.EventPacket; pending: BOOLEAN; param: ARRAY 2 OF CHAR;
  675. BEGIN
  676. IF context.arg.GetString(ident) & context.arg.GetInteger(handle, TRUE) THEN
  677. d := Find(ident);
  678. IF (d # NIL) THEN
  679. context.out.String("Reading clock offset for handle "); context.out.Int(handle, 0); context.out.String("... "); context.out.Ln;
  680. param[0] := CHR(handle MOD 100H); param[1] := CHR(handle DIV 100H MOD 100H);
  681. d.hci.SendCommand(HCI.ogfLinkControl, HCI.ocfReadClockOffset, param, 2, event, pending, res);
  682. IF (res = 0) THEN
  683. context.out.String(" waiting for response..."); context.out.Ln;
  684. d.hci.GetEvent(3000, event, res);
  685. IF (res = 0) THEN
  686. IF (event.code = 01CX) THEN
  687. res := ORD(event.params[0]);
  688. IF (res = 0) THEN
  689. handle := ORD(event.params[1])+LONG(ORD(event.params[2]))*100H;
  690. res := ORD(event.params[3])+LONG(ORD(event.params[4]))*100H;
  691. context.out.String(" success: clock offset for handle "); context.out.Hex(handle, -4); context.out.String(" is "); context.out.Int(res, 0)
  692. ELSE context.out.String(" failed; reason = "); context.out.Hex(res, -2)
  693. END
  694. ELSE context.out.String(" failed; wrong event ("); context.out.Hex(ORD(event.code), -2); context.out.String("X)")
  695. END
  696. ELSE context.out.String(" failed; error code = "); context.out.Hex(res, -2)
  697. END
  698. ELSE context.out.String("failed; error code = "); context.out.Hex(res, -2)
  699. END
  700. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  701. END
  702. ELSE context.out.String("Syntax error.")
  703. END;
  704. context.out.Ln;
  705. END ReadClockOffset;
  706. PROCEDURE SendACL*(context : Commands.Context);
  707. VAR
  708. ident: Ident; d: Device;
  709. data: ARRAY 256 OF CHAR; i, handle, cid, res: LONGINT; c1, c2: CHAR;
  710. l: HCI.Link;
  711. BEGIN
  712. IF context.arg.GetString(ident) & context.arg.GetInteger(handle, FALSE) & context.arg.GetInteger(cid, FALSE) THEN
  713. context.arg.SkipWhitespace;
  714. d := Find(ident);
  715. IF (d # NIL) THEN
  716. i := 4;
  717. WHILE (context.arg.res = Streams.Ok) DO
  718. c1 := context.arg.Get(); c2 := context.arg.Get();
  719. IF (context.arg.res = Streams.Ok) THEN
  720. data[i] := HexToChar(c1, c2);
  721. INC(i)
  722. END
  723. END;
  724. data[0] := CHR((i-4) MOD 100H); data[1] := CHR((i-4) DIV 100H); (* length *)
  725. data[2] := CHR(cid MOD 100H); data[3] := CHR(cid DIV 100H);
  726. context.out.String("Sending ACL data on link "); context.out.Int(handle, 0); context.out.String("...");
  727. l := d.hci.FindLink(handle, "");
  728. IF (l # NIL) THEN
  729. res := l.SendACL(HCI.pbfFirst, HCI.bfPointToPoint, data, 0, i);
  730. IF (res = 0) THEN context.out.String("success")
  731. ELSE context.out.String("failed; error code = "); context.out.Hex(res, -2)
  732. END
  733. ELSE context.out.String("link not found.")
  734. END
  735. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  736. END
  737. ELSE context.out.String("Syntax error.")
  738. END;
  739. context.out.Ln;
  740. END SendACL;
  741. PROCEDURE ReceiveData(handle, pb, bc, len: LONGINT; VAR data: ARRAY OF CHAR);
  742. VAR i: LONGINT;
  743. BEGIN
  744. KernelLog.String("Data received: ");
  745. FOR i := 0 TO len-1 DO KernelLog.Hex(ORD(data[i]), -2); KernelLog.Char(" ") END;
  746. KernelLog.Ln
  747. END ReceiveData;
  748. PROCEDURE TestStringToParam*(context : Commands.Context);
  749. (*
  750. VAR i, len: LONGINT; param: ARRAY 256 OF CHAR;
  751. BEGIN
  752. par := p(AosCommands.Parameters);
  753. Bluetooth.StringToParam(par.str^, param, len);
  754. FOR i := 0 TO len-1 DO
  755. KernelLog.Hex(ORD(param[i]), -2); KernelLog.Char(" ")
  756. END;
  757. KernelLog.Ln;
  758. RETURN NIL
  759. *)
  760. END TestStringToParam;
  761. PROCEDURE ReadBDAddr*(context : Commands.Context);
  762. VAR
  763. ident: Ident; d: Device;
  764. res, i: LONGINT; bdAddr: Bluetooth.BDAddr;
  765. BEGIN
  766. IF context.arg.GetString(ident) THEN
  767. d := Find(ident);
  768. IF (d # NIL) THEN
  769. res := d.hci.ReadBDAddr(bdAddr);
  770. IF (res = 0) THEN
  771. context.out.String("BDAddr = ");
  772. FOR i := 0 TO Bluetooth.BDAddrLen-1 DO context.out.Hex(ORD(bdAddr[i]), -2) END
  773. ELSE
  774. context.out.String("error (res = "); context.out.Int(res, 0); context.out.Char(")")
  775. END
  776. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  777. END
  778. ELSE context.out.String("Syntax error.")
  779. END;
  780. context.out.Ln;
  781. END ReadBDAddr;
  782. (*********************************************************************
  783. L2CAP
  784. **********************************************************************)
  785. PROCEDURE L2CAPInit*(context : Commands.Context);
  786. VAR ident: Ident; d: Device;
  787. BEGIN
  788. IF context.arg.GetString(ident) THEN
  789. d := Find(ident);
  790. IF (d # NIL) THEN
  791. L2CAP.InitL2CAP(d.hci);
  792. d.InitL2CAP
  793. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  794. END
  795. ELSE context.out.String("Syntax error.")
  796. END;
  797. context.out.Ln;
  798. END L2CAPInit;
  799. PROCEDURE L2CAPClose*(context : Commands.Context);
  800. VAR ident: Ident; d: Device;
  801. BEGIN
  802. IF context.arg.GetString(ident) THEN
  803. d := Find(ident);
  804. IF (d # NIL) THEN
  805. d.CloseL2CAP
  806. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  807. END
  808. ELSE context.out.String("Syntax error.")
  809. END;
  810. context.out.Ln;
  811. END L2CAPClose;
  812. PROCEDURE L2CAPConnect*(context : Commands.Context);
  813. VAR
  814. ident: Ident; d: Device;
  815. remote: Bluetooth.BDAddr; i, lcid, res, status: LONGINT;
  816. BEGIN
  817. context.arg.SkipWhitespace; context.arg.String(ident); context.arg.SkipWhitespace;
  818. FOR i := 0 TO LEN(remote)-1 DO remote[i] := HexToChar(context.arg.Get(), context.arg.Get()) END;
  819. IF (context.arg.res = Streams.Ok) THEN
  820. d := Find(ident);
  821. IF (d # NIL) THEN
  822. IF (d.l2cap # NIL) THEN
  823. context.out.String("Connecting to "); FOR i := 0 TO LEN(remote)-1 DO context.out.Hex(ORD(remote[i]), -2) END; context.out.String("..."); context.out.Ln;
  824. d.l2cap.Connect(L2CAP.psmSDP, remote, lcid, res, status);
  825. IF (res = 0) THEN
  826. context.out.String("connected."); context.out.Ln;
  827. context.out.String(" channel ID = "); context.out.Int(lcid, 0); context.out.Ln
  828. ELSE context.out.String("failed; error code = "); context.out.Hex(res, -2)
  829. END
  830. ELSE context.out.String("L2CAP not initialized.")
  831. END
  832. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  833. END
  834. ELSE context.out.String("Syntax error.")
  835. END;
  836. context.out.Ln;
  837. END L2CAPConnect;
  838. PROCEDURE L2CAPConfigure*(context : Commands.Context);
  839. VAR
  840. ident: Ident; d: Device;
  841. cid, res, mtu, flushTO, flow, linkTO: LONGINT;
  842. BEGIN
  843. IF context.arg.GetString(ident) & context.arg.GetInteger(cid, TRUE) & context.arg.GetInteger(mtu, TRUE) &
  844. context.arg.GetInteger(flushTO, TRUE) & context.arg.GetInteger(linkTO, TRUE) THEN
  845. d := Find(ident);
  846. IF (d # NIL) THEN
  847. IF (d.l2cap # NIL) THEN
  848. context.out.String("Configuring channel "); context.out.Int(cid, 0); context.out.String("..."); context.out.Ln;
  849. d.l2cap.Configure(cid, mtu, flow, flushTO, linkTO, res);
  850. IF (res = 0) THEN
  851. context.out.String("ok, channel is open")
  852. ELSE
  853. context.out.String("nope, res = "); context.out.Int(res, 0)
  854. END;
  855. context.out.Ln
  856. ELSE context.out.String("L2CAP not initialized.")
  857. END
  858. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  859. END
  860. ELSE context.out.String("Syntax error.")
  861. END;
  862. context.out.Ln;
  863. END L2CAPConfigure;
  864. PROCEDURE L2CAPPollChannel*(context : Commands.Context);
  865. VAR ident: Ident; d: Device; cid, mode: LONGINT;
  866. BEGIN
  867. IF context.arg.GetString(ident) & context.arg.GetInteger(cid, TRUE) & context.arg.GetInteger(mode, TRUE) THEN
  868. d := Find(ident);
  869. IF (d # NIL) THEN
  870. IF (d.l2cap # NIL) THEN
  871. IF mode = 1 THEN (* d.PollBytes(cid) *)
  872. ELSE(* d.Poll(cid) *)
  873. END
  874. ELSE context.out.String("L2CAP not initialized.")
  875. END
  876. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  877. END
  878. ELSE context.out.String("Syntax error.")
  879. END;
  880. context.out.Ln;
  881. END L2CAPPollChannel;
  882. PROCEDURE L2CAPSendString*(context : Commands.Context);
  883. VAR
  884. ident: Ident; d: Device;
  885. cid: LONGINT; str: ARRAY 65536 OF CHAR; i: LONGINT;
  886. BEGIN
  887. IF context.arg.GetString(ident) & context.arg.GetInteger(cid, TRUE) & context.arg.GetString(str) THEN
  888. d := Find(ident);
  889. IF (d # NIL) THEN
  890. IF (d.l2cap # NIL) THEN
  891. i := 0; WHILE (str[i] # 0X) DO INC(i) END;
  892. context.out.String("Length = "); context.out.Int(i, 0); context.out.Ln;
  893. d.SendString(cid, str);
  894. ELSE context.out.String("L2CAP not initialized.")
  895. END
  896. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  897. END
  898. ELSE context.out.String("Syntax error.")
  899. END;
  900. context.out.Ln;
  901. END L2CAPSendString;
  902. PROCEDURE L2CAPPing*(context : Commands.Context);
  903. VAR
  904. ident: Ident; d: Device;
  905. remote: Bluetooth.BDAddr; i, len, res: LONGINT; data: ARRAY 32 OF CHAR;
  906. BEGIN
  907. context.arg.SkipWhitespace; context.arg.String(ident); context.arg.SkipWhitespace;
  908. FOR i := 0 TO LEN(remote)-1 DO remote[i] := HexToChar(context.arg.Get(), context.arg.Get()) END;
  909. IF (context.arg.res = Streams.Ok) THEN
  910. d := Find(ident);
  911. IF (d # NIL) THEN
  912. IF (d.l2cap # NIL) THEN
  913. context.out.String("Pinging "); FOR i := 0 TO LEN(remote)-1 DO context.out.Hex(ORD(remote[i]), -2) END; context.out.String("..."); context.out.Ln;
  914. d.l2cap.Ping(remote, data, len, res);
  915. IF (res = 0) THEN
  916. context.out.String("success."); context.out.Ln;
  917. ELSE context.out.String("failed; error code = "); context.out.Hex(res, -2)
  918. END
  919. ELSE context.out.String("L2CAP not initialized.")
  920. END
  921. ELSE context.out.String("No such device '"); context.out.String(ident); context.out.String("'.")
  922. END
  923. ELSE context.out.String("Syntax error.")
  924. END;
  925. context.out.Ln;
  926. END L2CAPPing;
  927. PROCEDURE Cleanup;
  928. VAR d: Device;
  929. BEGIN
  930. d := devices.next;
  931. IF (d # NIL) THEN
  932. KernelLog.String("Automatic shutdown: ");
  933. WHILE (d # NIL) DO
  934. KernelLog.String(d.ident); KernelLog.Char(" ");
  935. d.hci.Close;
  936. d.port.Close;
  937. d := d.next
  938. END;
  939. KernelLog.Ln
  940. END;
  941. END Cleanup;
  942. BEGIN
  943. Modules.InstallTermHandler(Cleanup);
  944. NEW(devices); (* dummy head *)
  945. END BluetoothTest.
  946. (*
  947. BluetoothHCI.Mod
  948. SystemTools.Free BluetoothTest BluetoothL2CAP BluetoothHCI BluetoothUART BluetoothUSB Bluetooth~
  949. SystemTools.Free BluetoothTest~
  950. SystemTools.ListPlugins ~
  951. BluetoothTest.Open UsbBluetooth00 BTTest ~
  952. BluetoothTest.Reset BTTest ~
  953. **** HCI level ****
  954. BluetoothTest.ReadLocalName BTTest ~
  955. BluetoothTest.ChangeLocalName BTTest aRealName ~
  956. BluetoothTest.ReadClassOfDevice BTTest ~
  957. BluetoothTest.WriteClassOfDevice BTTest 040420 ~
  958. BluetoothTest.ReadBDAddr BTTest ~
  959. BluetoothTest.ReadLocalSupportedFeatures BTTest ~
  960. BluetoothTest.ReadScanEnable BTTest ~
  961. BluetoothTest.WriteScanEnable BTTest 03 ~
  962. BluetoothTest.ReadPageScanActivity BTTest ~
  963. BluetoothTest.WritePageScanActivity BTTest 1024 25 ~
  964. BluetoothTest.ReadInquiryScanActivity BTTest ~
  965. BluetoothTest.WriteInquiryScanActivity BTTest 0801H 013H ~
  966. BluetoothTest.Inquiry BTTest 9E8B33 08H 0 ~
  967. BluetoothTest.ListHCIConnections BTTest ~ Aos.Call BluetoothTest.ListHCIConnections huga ~
  968. Configuration.DoCommands
  969. Aos.Call \w BluetoothTest.Open BTTest 1 57600 8 0 1~
  970. Aos.Call \w BluetoothTest.L2CAPInit BTTest ~
  971. Aos.Call \w BluetoothTest.WriteScanEnable BTTest 03~
  972. Aos.Call \w BluetoothTest.SetFilter BTTest ~
  973. ~
  974. Configuration.DoCommands
  975. Aos.Call \w BluetoothTest.Open huga 2 57600 8 0 1~
  976. Aos.Call \w BluetoothTest.L2CAPInit huga ~
  977. Aos.Call \w BluetoothTest.WriteScanEnable huga 03~
  978. Aos.Call \w BluetoothTest.SetFilter huga ~
  979. ~
  980. Aos.Call BluetoothTest.L2CAPConnect BTTest 4578ACD90A00 ~
  981. Aos.Call BluetoothTest.L2CAPPing BTTest 820914378000 ~
  982. Aos.Call BluetoothTest.L2CAPConnect BTTest 94CB16378000 ~
  983. Aos.Call BluetoothTest.L2CAPConfigure BTTest 3 16384 0 0 ~
  984. Aos.Call BluetoothTest.L2CAPPollChannel BTTest 3 1 ~
  985. Aos.Call BluetoothTest.L2CAPSendString BTTest 3 hello-philipp ~
  986. ~
  987. Configuration.DoCommands
  988. Aos.Call \w BluetoothTest.Reset BTTest ~
  989. Aos.Call \w BluetoothTest.Reset huga ~
  990. Aos.Call \w BluetoothTest.Close BTTest ~
  991. Aos.Call \w BluetoothTest.Close huga ~
  992. System.Free BluetoothTest V24IO V24 BTConnector BluetoothL2CAP BluetoothStream BluetoothHCI BluetoothUART Bluetooth~
  993. ~
  994. **** open device ****
  995. Aos.Call BluetoothTest.Open BTTest 1 57600 8 0 1~ Aos.Call BluetoothTest.Open huga 2 57600 8 0 1 R~
  996. Aos.Call BluetoothTest.Close BTTest ~ Aos.Call BluetoothTest.Close huga ~
  997. Aos.Call BluetoothTest.TraceMode BTTest T ~ Aos.Call BluetoothTest.TraceMode huga R ~
  998. **** L2CAP ****
  999. Aos.Call BluetoothTest.L2CAPInit BTTest ~ Aos.Call BluetoothTest.L2CAPInit huga ~
  1000. Aos.Call BluetoothTest.L2CAPClose BTTest ~ Aos.Call BluetoothTest.L2CAPClose huga ~
  1001. Aos.Call BluetoothTest.L2CAPPing BTTest 820914378000 ~
  1002. Aos.Call BluetoothTest.L2CAPPing BTTest CB0814378000 ~
  1003. Aos.Call BluetoothTest.L2CAPPing BTTest 6BF257DC1000 ~
  1004. Aos.Call BluetoothTest.L2CAPPing BTTest 98CB16378000 ~
  1005. Aos.Call BluetoothTest.L2CAPSendInfoReq BTTest 820914378000 ~
  1006. Aos.Call BluetoothTest.L2CAPConnect BTTest 95CB16378000 ~
  1007. Aos.Call BluetoothTest.L2CAPConnect BTTest 6BF257DC1000 ~
  1008. Aos.Call BluetoothTest.L2CAPConnect BTTest 65B316378000 ~
  1009. Aos.Call BluetoothTest.L2CAPConnect BTTest 820914378000 ~
  1010. Aos.Call BluetoothTest.L2CAPConnect BTTest BFA1EE378000 ~
  1011. Aos.Call BluetoothTest.L2CAPConfigure BTTest 3 1200 0 0 ~
  1012. **** HCI level ****
  1013. Aos.Call BluetoothTest.ReadLocalName BTTest ~ Aos.Call BluetoothTest.ReadLocalName huga ~
  1014. Aos.Call BluetoothTest.ChangeLocalName BTTest romiro ~ Aos.Call BluetoothTest.ChangeLocalName huga huga ~
  1015. Aos.Call BluetoothTest.ReadClassOfDevice BTTest ~ Aos.Call BluetoothTest.ReadClassOfDevice huga ~
  1016. Aos.Call BluetoothTest.WriteClassOfDevice BTTest 040420 ~ Aos.Call BluetoothTest.WriteClassOfDevice huga 040420 ~
  1017. Aos.Call BluetoothTest.ReadBDAddr BTTest ~ Aos.Call BluetoothTest.ReadBDAddr huga ~
  1018. Aos.Call BluetoothTest.ReadLocalSupportedFeatures BTTest ~ Aos.Call BluetoothTest.ReadLocalSupportedFeatures huga ~
  1019. Aos.Call BluetoothTest.ReadScanEnable BTTest ~ Aos.Call BluetoothTest.ReadScanEnable huga ~
  1020. Aos.Call BluetoothTest.WriteScanEnable BTTest 03 ~ Aos.Call BluetoothTest.WriteScanEnable huga 03 ~
  1021. Aos.Call BluetoothTest.ReadPageScanActivity BTTest ~ Aos.Call BluetoothTest.ReadPageScanActivity huga ~
  1022. Aos.Call BluetoothTest.WritePageScanActivity BTTest 1024 25~ Aos.Call BluetoothTest.WritePageScanActivity huga 4096 20~
  1023. Aos.Call BluetoothTest.ReadInquiryScanActivity BTTest ~ Aos.Call BluetoothTest.ReadInquiryScanActivity huga ~
  1024. Aos.Call BluetoothTest.WriteInquiryScanActivity BTTest 0801H 013H~ Aos.Call BluetoothTest.WriteInquiryScanActivity huga ~
  1025. Aos.Call BluetoothTest.Inquiry BTTest 9E8B33 08H 0~ Aos.Call BluetoothTest.Inquiry huga 9E8B33 08H 0~
  1026. Aos.Call BluetoothTest.ListHCIConnections BTTest ~ Aos.Call BluetoothTest.ListHCIConnections huga ~
  1027. Aos.Call BluetoothTest.Reset BTTest ~ Aos.Call BluetoothTest.Reset huga ~
  1028. Aos.Call BluetoothTest.WriteScanEnable BTTest 03~ Aos.Call BluetoothTest.WriteScanEnable huga 03~
  1029. Aos.Call BluetoothTest.SetFilter BTTest ~ Aos.Call BluetoothTest.SetFilter huga ~
  1030. Aos.Call BluetoothTest.ConnectTo BTTest 95CB16378000 0~ Aos.Call BluetoothTest.ConnectTo huga CB0814378000 0~
  1031. Aos.Call BluetoothTest.ConnectTo BTTest BFA1EE378000 0~ Aos.Call BluetoothTest.ConnectTo huga 96CB16378000 0~
  1032. Aos.Call BluetoothTest.ConnectTo BTTest CB0814378000 0~
  1033. Aos.Call BluetoothTest.ConnectTo BTTest 820914378000 0~
  1034. Aos.Call BluetoothTest.ReadClockOffset BTTest 2 ~ Aos.Call BluetoothTest.ReadClockOffset huga 1 ~
  1035. Aos.Call BluetoothTest.SendACL BTTest 1 0 414243444546~ Aos.Call BluetoothTest.SendACL huga 1 0 01~
  1036. Aos.Call BluetoothTest.TestStringToParam 00 01 02 FF 04 05 06~
  1037. *)