MODULE BluetoothUART;
IMPORT
KernelLog, Streams, Bluetooth, Objects;
CONST
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;
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());
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());
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
KernelLog.String(ModuleName);
KernelLog.String("TransportLayer.Read: uartCommand received! closing layer");
KernelLog.Ln;
Close;
RETURN;
ELSIF (ch = uartACLData) THEN
packet := ReadACLPacket();
queue := sink[Bluetooth.ACL];
ELSIF (ch = uartSCOData) THEN
packet := ReadSCOPacket();
queue := sink[Bluetooth.SCO];
ELSIF (ch = uartEvent) THEN
packet := ReadEventPacket();
queue := sink[Bluetooth.Event];
ELSE
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: LONGINT);
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: LONGINT);
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: LONGINT);
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.