123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- MODULE BluetoothUART; (** AUTHOR "be"; PURPOSE "HCI UART transport layer"; *)
- IMPORT
- KernelLog, Streams, Bluetooth, Objects;
- (* HCI command packet format (RS-232)
- | 01X | opcode (2bytes) | total parameter length | par0 | ... | parN |; and opcode = OGF (6bit) || OCF (10bit)
- HCI ACL data packet format (RS-232)
- | 02X |
- HCI SCO data packet format (RS-232)
- | 03X |
- HCI event packet format (RS-232)
- | 04X | Event Code | total parameter length | par0 | ... | parN |
- Error message packed format (RS-232)
- | 05X |
- Negotiation packet format (RS-232)
- | 06X |
- *)
- CONST
- (*
- TraceSend = FALSE;
- TraceReceive = FALSE;
- *)
- ModuleName = "[BTUART]";
- uartCommand = 01X;
- uartACLData = 02X;
- uartSCOData = 03X;
- uartEvent = 04X;
- TYPE
- TransportLayer* = OBJECT(Bluetooth.TransportLayer)
- VAR
- TraceReceive*, TraceSend*: BOOLEAN;
- dead-: BOOLEAN;
- PROCEDURE &Init*(name: ARRAY OF CHAR; sender: Streams.Sender; receiver: Streams.Receiver);
- BEGIN
- Init^(name, sender, receiver);
- NEW(out, sender, 512); NEW(in, receiver, 512);
- dead := FALSE;
- TraceReceive := FALSE; TraceSend := FALSE;
- END Init;
- PROCEDURE Close*;
- BEGIN {EXCLUSIVE}
- dead := TRUE
- END Close;
- PROCEDURE IsOpen*() :BOOLEAN;
- BEGIN {EXCLUSIVE}
- RETURN ~dead;
- END IsOpen;
- PROCEDURE ReadACLPacket() : Bluetooth.Packet;
- VAR acl: Bluetooth.ACLPacket; i : LONGINT;
- BEGIN
- NEW(acl);
- i := ORD(in.Get()) + ORD(in.Get())*100H;
- acl.handle := i MOD 1000H;
- acl.PB := (i DIV 1000H) MOD 4;
- acl.BC := (i DIV 4000H) MOD 4;
- acl.len := ORD(in.Get()) + ORD(in.Get())*100H;
- (*ASSERT(acl.len <= Bluetooth.MaxACLDataLen);*)
- IF (acl.len > Bluetooth.MaxACLDataLen) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadACLPacket: acl.len > Bluetooth.MaxACLDataLen");
- KernelLog.Ln;
- KernelLog.String("acl.len= "); KernelLog.Int(acl.len, 0);
- KernelLog.String("; BluetoothMaxACLDataLen= "); KernelLog.Int(Bluetooth.MaxACLDataLen, 0);
- KernelLog.String("; in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.Ln;
- RETURN NIL;
- END;
- FOR i := 0 TO acl.len-1 DO
- acl.data[i] := in.Get();
- END;
- IF (in.res # 0) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadACLPacket: UART failure; in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.Ln;
- RETURN NIL;
- END;
- IF TraceReceive THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadACLPacket: reading ACL data");
- KernelLog.Ln;
- KernelLog.String("handle= 0x");KernelLog.Hex(acl.handle,-2);
- KernelLog.String("; packet boundary= 0x");KernelLog.Hex(acl.PB,-2);
- KernelLog.String("; broadcast= 0x"); KernelLog.Hex(acl.BC,-2);
- KernelLog.String("; payload length= 0x"); KernelLog.Int(acl.len,0);
- KernelLog.String("; acl.data= ");
- FOR i := 0 TO acl.len-1 DO
- KernelLog.String(" 0x"); KernelLog.Hex(ORD(acl.data[i]),-2);
- END;
- KernelLog.Ln;
- END;
- RETURN acl;
- END ReadACLPacket;
- PROCEDURE ReadSCOPacket() : Bluetooth.Packet;
- VAR sco: Bluetooth.SCOPacket; i : LONGINT;
- BEGIN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadSCOPacket: uartSCOData received!! continue ....");
- KernelLog.Ln;
- NEW(sco);
- i := ORD(in.Get()) + ORD(in.Get())*100H;
- sco.handle := i MOD 1000H;
- sco.len := ORD(in.Get());
- (*ASSERT(sco.len <= Bluetooth.MaxSCODataLen);*)
- IF (sco.len > Bluetooth.MaxSCODataLen) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadSCOPacket: sco.len > Bluetooth.MaxSCODataLen");
- KernelLog.Ln;
- KernelLog.String("sco.len= "); KernelLog.Int(sco.len, 0);
- KernelLog.String("; BluetoothMaxACLDataLen= "); KernelLog.Int(Bluetooth.MaxSCODataLen, 0);
- KernelLog.String("; in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.Ln;
- RETURN NIL;
- END;
- FOR i := 0 TO sco.len-1 DO
- sco.data[i] := in.Get();
- END;
- IF (in.res # 0) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadSCOPacket: UART failure; in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.Ln;
- RETURN NIL;
- END;
- IF TraceReceive THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadSCOPacket: reading SCO data");
- KernelLog.Ln;
- KernelLog.String("handle= 0x");KernelLog.Hex(sco.handle,-2);
- KernelLog.String(" payload length= 0x"); KernelLog.Int(sco.len,0);
- KernelLog.String("; sco.data= ");
- FOR i := 0 TO sco.len-1 DO
- KernelLog.String(" 0x"); KernelLog.Hex(ORD(sco.data[i]),-2);
- END;
- KernelLog.Ln;
- END;
- RETURN sco;
- END ReadSCOPacket;
- PROCEDURE ReadEventPacket() : Bluetooth.Packet;
- VAR event: Bluetooth.EventPacket; i : LONGINT;
- BEGIN
- NEW(event);
- event.code :=in. Get();
- event.paramLen := ORD(in.Get());
- (*ASSERT(event.paramLen < Bluetooth.MaxEventParamLen);*)
- IF (event.paramLen > Bluetooth.MaxEventParamLen) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadEventPacket: paramLen > MaxParamLen");
- KernelLog.Ln;
- KernelLog.String("paramLen= "); KernelLog.Int(event.paramLen, 0);
- KernelLog.String("; MaxParamLen= "); KernelLog.Int(Bluetooth.MaxEventParamLen, 0);
- KernelLog.String("; in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.Ln;
- END;
- FOR i := 0 TO event.paramLen-1 DO
- event.params[i] := in.Get();
- END;
- IF (in.res # 0) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadEventPacket: UART failure; in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.Ln;
- RETURN NIL;
- END;
- IF TraceReceive THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadEventPacket: reading event Data");
- KernelLog.Ln;
- KernelLog.String("event.code = 0x"); KernelLog.Hex(ORD(event.code),-2);
- KernelLog.String("; event.paramLen= "); KernelLog.Int(event.paramLen,0);
- KernelLog.String("; event.params= ");
- FOR i := 0 TO event.paramLen-1 DO
- KernelLog.String(" 0x"); KernelLog.Hex(ORD(event.params[i]),-2);
- END;
- KernelLog.Ln;
- END;
- RETURN event;
- END ReadEventPacket;
- PROCEDURE ReadUnknownPacket() : Bluetooth.Packet;
- VAR unknown: Bluetooth.UnknownPacket; ch : CHAR;
- BEGIN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.ReadUnknownPacket: unknown/invalid packet ch= 0x"); KernelLog.Hex(ORD(ch),-2);
- KernelLog.String("; in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.String("; in.Available()= "); KernelLog.Int(in.Available(), 0);
- KernelLog.Ln;
- NEW(unknown);
- unknown.len := 0;
- WHILE ((in.Available() > 0) & (in.res = 0)) DO
- IF(unknown.len < Bluetooth.MaxUnknownDataLen) THEN
- unknown.data[unknown.len] := in.Get();
- KernelLog.String("unknown.data["); KernelLog.Int(unknown.len,0); KernelLog.String("]= 0x");
- KernelLog.Hex(ORD(unknown.data[unknown.len]),-2);
- KernelLog.String("; in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.Ln;
- INC(unknown.len);
- ELSE
- ch := in.Get();
- KernelLog.String("discard ch= 0x"); KernelLog.Hex(ORD(ch),-2);
- KernelLog.String("; in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.Ln;
- END;
- END;
- RETURN unknown;
- END ReadUnknownPacket;
- PROCEDURE Read;
- VAR
- ch: CHAR;
- queue: Bluetooth.Queue;
- packet: Bluetooth.Packet;
- BEGIN
- ch := in.Get();
- IF (in.res # 0) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Read: UART failure in.res= 0x"); KernelLog.Hex(in.res, -2);
- KernelLog.String("; closing layer");
- KernelLog.Ln;
- Close;
- RETURN;
- END;
- IF (ch = uartCommand) THEN (* HCI command packet *)
- (*HALT(100) (* not sent by host controller *)*)
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Read: uartCommand received! closing layer");
- KernelLog.Ln;
- Close;
- RETURN;
- ELSIF (ch = uartACLData) THEN (* HCI ACL data packet *)
- packet := ReadACLPacket();
- queue := sink[Bluetooth.ACL];
- ELSIF (ch = uartSCOData) THEN (* HCI SCO data packet *)
- packet := ReadSCOPacket();
- queue := sink[Bluetooth.SCO];
- ELSIF (ch = uartEvent) THEN (* HCI event packet *)
- packet := ReadEventPacket();
- queue := sink[Bluetooth.Event];
- ELSE (* unknown/invalid packet *)
- packet := ReadUnknownPacket();
- queue := sink[Bluetooth.Default];
- END;
- IF (packet = NIL) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Read: error while reading packet; ch= "); KernelLog.Char(ch);
- KernelLog.String("; in.res= "); KernelLog.Int(in.res, 0);
- KernelLog.String("; closing layer");
- KernelLog.Ln;
- Close;
- RETURN;
- ELSE
- queue.Add(packet);
- END;
- IF TraceReceive THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Read done.");
- KernelLog.String(" in.Available()= "); KernelLog.Int(in.Available(), 0);
- KernelLog.Ln;
- END;
- END Read;
- PROCEDURE GetPacketType(type: LONGINT; VAR c: CHAR): BOOLEAN;
- VAR res: BOOLEAN;
- BEGIN
- res := TRUE;
- CASE type OF
- | Bluetooth.Command: c := uartCommand
- | Bluetooth.ACL: c := uartACLData
- | Bluetooth.SCO: c := uartSCOData
- ELSE res := FALSE
- END;
- RETURN res
- END GetPacketType;
- PROCEDURE Send*(type: LONGINT; VAR data: ARRAY OF CHAR; ofs, len: LONGINT; VAR res: WORD);
- VAR pt: CHAR; i: LONGINT;
- BEGIN {EXCLUSIVE}
- IF ~GetPacketType(type, pt) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Send: wrong packet type= 0x"); KernelLog.Hex(type,-2);
- KernelLog.Ln;
- res := Bluetooth.ErrInvalidParameters;
- RETURN
- END;
- IF TraceSend THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Send: packet type= 0x"); KernelLog.Hex(ORD(pt), -2);
- FOR i := 0 TO len-1 DO
- KernelLog.Char(" ");
- KernelLog.Hex(ORD(data[ofs+i]), -2);
- END;
- KernelLog.Ln
- END;
- out.Char(pt); out.Bytes(data, ofs, len); out.Update;
- res := out.res
- END Send;
- PROCEDURE Send1H*(type: LONGINT; VAR hdr: ARRAY OF CHAR; hdrlen: LONGINT; VAR data: ARRAY OF CHAR; ofs, len: LONGINT; VAR res: WORD);
- VAR pt: CHAR; i: LONGINT;
- BEGIN
- IF ~GetPacketType(type, pt) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Send1H: wrong packet type= 0x"); KernelLog.Hex(type,-2);
- KernelLog.Ln;
- res := Bluetooth.ErrInvalidParameters;
- RETURN
- END;
- IF TraceSend THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Send1H: packet type= 0x"); KernelLog.Hex(ORD(pt), -2);
- FOR i := 0 TO hdrlen-1 DO
- KernelLog.Char(" "); KernelLog.Hex(ORD(hdr[i]), -2);
- END;
- FOR i := 0 TO len-1 DO
- KernelLog.Char(" "); KernelLog.Hex(ORD(data[ofs+i]), -2);
- END;
- KernelLog.Ln
- END;
- out.Char(pt); out.Bytes(hdr, 0, hdrlen); out.Bytes(data, ofs, len); out.Update;
- res := out.res
- END Send1H;
- PROCEDURE Send2H*(type: LONGINT; VAR hdr1: ARRAY OF CHAR; hdr1len: LONGINT;
- VAR hdr2: ARRAY OF CHAR; hdr2len: LONGINT;
- VAR data: ARRAY OF CHAR; ofs, len: LONGINT; VAR res: WORD);
- VAR pt: CHAR; i: LONGINT;
- BEGIN
- IF ~GetPacketType(type, pt) THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Send2H: wrong packet type= 0x"); KernelLog.Hex(type,-2);
- KernelLog.Ln;
- res := Bluetooth.ErrInvalidParameters;
- RETURN
- END;
- IF TraceSend THEN
- KernelLog.String(ModuleName);
- KernelLog.String("TransportLayer.Send2H: packet type= 0x"); KernelLog.Hex(ORD(pt), -2);
- FOR i := 0 TO hdr1len-1 DO
- KernelLog.Char(" "); KernelLog.Hex(ORD(hdr1[i]), -2);
- END;
- FOR i := 0 TO hdr2len-1 DO
- KernelLog.Char(" "); KernelLog.Hex(ORD(hdr2[ofs+i]), -2);
- END;
- FOR i := 0 TO len-1 DO
- KernelLog.Char(" "); KernelLog.Hex(ORD(data[ofs+i]), -2);
- END;
- KernelLog.Ln
- END;
- out.Char(pt); out.Bytes(hdr1, 0, hdr1len); out.Bytes(hdr2, 0, hdr2len); out.Bytes(data, ofs, len); out.Update;
- res := out.res
- END Send2H;
- BEGIN {ACTIVE}
- Objects.SetPriority(3);
- REPEAT
- Read;
- UNTIL dead
- END TransportLayer;
- END BluetoothUART.
|