302 lines
11 KiB
C#
302 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net.NetworkInformation;
|
|
using System.Numerics;
|
|
using System.Runtime.Intrinsics.X86;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using skyscraper5.Docsis.AnnexC;
|
|
using skyscraper5.Skyscraper;
|
|
using skyscraper5.Skyscraper.IO;
|
|
using skyscraper5.Skyscraper.Plugins;
|
|
|
|
namespace skyscraper5.Docsis.MacManagement
|
|
{
|
|
[SkyscraperPlugin]
|
|
[MacManagementMessageType(1,5)]
|
|
[MacManagementMessageType(5,5)]
|
|
public class RangingResponse : MacManagementMessage
|
|
{
|
|
public RangingResponse(PhysicalAddress source, PhysicalAddress destination, byte[] buffer) : base(source, destination, buffer)
|
|
{
|
|
MemoryStream ms = new MemoryStream(buffer, false);
|
|
SID = ms.ReadUInt16BE();
|
|
UpstreamChannelId = ms.ReadUInt8();
|
|
long positionFor1516;
|
|
|
|
while (ms.GetAvailableBytes() > 2)
|
|
{
|
|
positionFor1516 = ms.Position;
|
|
byte type = ms.ReadUInt8();
|
|
byte length = ms.ReadUInt8();
|
|
if (length > ms.GetAvailableBytes())
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
if (length == 0)
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
byte[] v = ms.ReadBytes(length);
|
|
switch (type)
|
|
{
|
|
case 0:
|
|
//reserved
|
|
break;
|
|
case 1:
|
|
if (length < 4)
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
(v[0], v[1], v[2], v[3]) = (v[3], v[2], v[1], v[0]);
|
|
TimingAdjust = BitConverter.ToUInt32(v, 0);
|
|
break;
|
|
case 2:
|
|
PowerLevelAdjust = v[0];
|
|
break;
|
|
case 3:
|
|
if (length < 2)
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
(v[0], v[1]) = (v[1], v[0]);
|
|
OffsetFrequencyAdjust = BitConverter.ToUInt16(v, 0);
|
|
break;
|
|
case 4:
|
|
TxEqualizationData = v;
|
|
break;
|
|
case 5:
|
|
RangingStatus = (RangingStatusEnum)v[0];
|
|
break;
|
|
case 6:
|
|
if (length < 4)
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
(v[0], v[1], v[2], v[3]) = (v[3], v[2], v[1], v[0]);
|
|
DownstreamFrequencyOverride = BitConverter.ToUInt32(v, 0);
|
|
break;
|
|
case 7:
|
|
UpstreamChannelIdOverride = v[0];
|
|
break;
|
|
case 8:
|
|
TimingAdjustFractionalPart = v[0];
|
|
break;
|
|
case 9:
|
|
TransmitEqualizationSet = v;
|
|
break;
|
|
case 10:
|
|
SCdmaMaximumScheduledCodes = v[0];
|
|
break;
|
|
case 11:
|
|
SCdmaPowerHeadroom = v[0];
|
|
break;
|
|
case 12:
|
|
byte[] upstreamChannelAdjustmentsBuffer = ms.ReadBytes(length);
|
|
UpstreamChannelAdjustments = new UpstreamChannelAdjustmentsObject(upstreamChannelAdjustmentsBuffer);
|
|
break;
|
|
case 13:
|
|
T4TimeoutMultiplier = v[0];
|
|
break;
|
|
case 14:
|
|
DynamicRangeWindowUpperEdge = ((double)v[0]) * 0.25;
|
|
break;
|
|
case 15:
|
|
case 16:
|
|
ms.Position = positionFor1516;
|
|
byte type2 = ms.ReadUInt8();
|
|
ushort newLen = ms.ReadUInt16BE();
|
|
if (ms.GetAvailableBytes() < newLen)
|
|
{
|
|
newLen = (ushort)ms.GetAvailableBytes();
|
|
}
|
|
v = ms.ReadBytes(newLen);
|
|
TransmitEqualizationEncodingsForOfdmaChannels result1516 = Parse1516(v);
|
|
if (type == 15)
|
|
TransmitEqualizationAdjustForOfdmaChannels = Parse1516(v);
|
|
else if (type == 16)
|
|
TransmitEqualizationSetForOfdmaChannels = Parse1516(v);
|
|
else
|
|
throw new NotImplementedException(String.Format("2-byte TLV entry in Ranging Response with ID {0}", type));
|
|
break;
|
|
case 17:
|
|
CommandPower = new CommandPowerObject(v);
|
|
if (!CommandPower.Valid)
|
|
{
|
|
CommandPower = null;
|
|
Valid = false;
|
|
return;
|
|
}
|
|
break;
|
|
case 18:
|
|
FdxCommandedPower = new CommandPowerObject(v);
|
|
if (!FdxCommandedPower.Valid)
|
|
{
|
|
FdxCommandedPower = null;
|
|
Valid = false;
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
if (type > 18)
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
//see CM-SP-MULPIv4.0-I01-190815.pdf page 141
|
|
throw new NotImplementedException(String.Format("{0} Type {1}", nameof(RangingResponse), type));
|
|
}
|
|
}
|
|
Valid = true;
|
|
}
|
|
|
|
public byte[] TransmitEqualizationSet { get; private set; }
|
|
|
|
private TransmitEqualizationEncodingsForOfdmaChannels Parse1516(byte[] buffer)
|
|
{
|
|
MemoryStream ms = new MemoryStream(buffer);
|
|
byte l = ms.ReadUInt8();
|
|
byte m = ms.ReadUInt8();
|
|
byte r = ms.ReadUInt8();
|
|
TransmitEqualizationEncodingsForOfdmaChannels result = new TransmitEqualizationEncodingsForOfdmaChannels();
|
|
result.LowestSubcarrier = (l << 4);
|
|
result.LowestSubcarrier += ((m & 0xf0) >> 4);
|
|
result.HighestSubcarrier = (m & 0x0f);
|
|
result.HighestSubcarrier <<= 4;
|
|
result.HighestSubcarrier += r;
|
|
|
|
long numCoefficents = ms.GetAvailableBytes() / 4;
|
|
result.Coefficients = new Complex[numCoefficents];
|
|
for (int i = 0; i < numCoefficents; i++)
|
|
{
|
|
ushort real = ms.ReadUInt16BE();
|
|
ushort imaginary = ms.ReadUInt16BE();
|
|
result.Coefficients[i] = new Complex(real, imaginary);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public TransmitEqualizationEncodingsForOfdmaChannels TransmitEqualizationAdjustForOfdmaChannels { get; private set; }
|
|
private CommandPowerObject CommandPower { get; set; }
|
|
class CommandPowerObject : Validatable
|
|
{
|
|
public CommandPowerObject(byte[] buffer)
|
|
{
|
|
if (buffer.Length < 2)
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
|
|
MemoryStream ms = new MemoryStream(buffer, false);
|
|
while (ms.GetAvailableBytes() > 2)
|
|
{
|
|
byte type = ms.ReadUInt8();
|
|
byte length = ms.ReadUInt8();
|
|
if (length > ms.GetAvailableBytes())
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
byte[] v = ms.ReadBytes(length);
|
|
switch (type)
|
|
{
|
|
case 1:
|
|
DynamicRangeWindow = v[0];
|
|
break;
|
|
case 2:
|
|
TransmitPowerLevels = v;
|
|
break;
|
|
default:
|
|
Valid = false;
|
|
return;
|
|
}
|
|
}
|
|
Valid = true;
|
|
}
|
|
|
|
public byte[] TransmitPowerLevels { get; set; }
|
|
|
|
public byte? DynamicRangeWindow { get; set; }
|
|
}
|
|
|
|
public byte? T4TimeoutMultiplier { get; set; }
|
|
|
|
public byte[] TxEqualizationData { get; set; }
|
|
|
|
public byte? PowerLevelAdjust { get; set; }
|
|
|
|
public RangingStatusEnum? RangingStatus { get; private set; }
|
|
|
|
public enum RangingStatusEnum : byte
|
|
{
|
|
Continue = 1,
|
|
Abort = 2,
|
|
Success = 3
|
|
}
|
|
|
|
public ushort? OffsetFrequencyAdjust { get; set; }
|
|
|
|
public uint? TimingAdjust { get; set; }
|
|
|
|
public ushort? UpstreamChannelId { get; set; }
|
|
|
|
public ushort? SID { get; set; }
|
|
public TransmitEqualizationEncodingsForOfdmaChannels TransmitEqualizationSetForOfdmaChannels { get; private set; }
|
|
public double? DynamicRangeWindowUpperEdge { get; private set; }
|
|
public uint? DownstreamFrequencyOverride { get; }
|
|
public byte? UpstreamChannelIdOverride { get; private set; }
|
|
public byte? SCdmaPowerHeadroom { get; }
|
|
public UpstreamChannelAdjustmentsObject UpstreamChannelAdjustments { get; private set; }
|
|
private CommandPowerObject FdxCommandedPower { get; }
|
|
public byte? TimingAdjustFractionalPart { get; }
|
|
public byte? SCdmaMaximumScheduledCodes { get; }
|
|
|
|
public class UpstreamChannelAdjustmentsObject : Validatable
|
|
{
|
|
public UpstreamChannelAdjustmentsObject(byte[] buffer)
|
|
{
|
|
MemoryStream ms = new MemoryStream(buffer, false);
|
|
|
|
while (ms.GetAvailableBytes() > 2)
|
|
{
|
|
byte type = ms.ReadUInt8();
|
|
byte length = ms.ReadUInt8();
|
|
if (length > ms.GetAvailableBytes())
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
byte[] v = ms.ReadBytes(length);
|
|
switch (type)
|
|
{
|
|
default:
|
|
if (type > 6)
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
//See CM-SP-MULPIv4.0-I01-190815.pdf page 142
|
|
throw new NotImplementedException(String.Format("{0} TLV Type {1}", nameof(UpstreamChannelAdjustmentsObject), type));
|
|
}
|
|
}
|
|
Valid = true;
|
|
}
|
|
}
|
|
|
|
public class TransmitEqualizationEncodingsForOfdmaChannels
|
|
{
|
|
public int LowestSubcarrier { get; internal set; }
|
|
public int HighestSubcarrier { get; internal set; }
|
|
public Complex[] Coefficients { get; internal set; }
|
|
}
|
|
}
|
|
}
|