1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.uwb.params; 18 19 import static com.android.server.uwb.config.CapabilityParam.CCC_CHANNEL_5; 20 import static com.android.server.uwb.config.CapabilityParam.CCC_CHANNEL_9; 21 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_12; 22 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_24; 23 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_3; 24 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_4; 25 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_6; 26 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_8; 27 import static com.android.server.uwb.config.CapabilityParam.CCC_CHAPS_PER_SLOT_9; 28 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_CONFIG_MODE_ADAPTIVE; 29 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_CONFIG_MODE_CONTINUOUS; 30 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_CONFIG_MODE_NONE; 31 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_SEQUENCE_AES; 32 import static com.android.server.uwb.config.CapabilityParam.CCC_HOPPING_SEQUENCE_DEFAULT; 33 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_CHANNELS; 34 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_CHAPS_PER_SLOT; 35 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_HOPPING_CONFIG_MODES_AND_SEQUENCES; 36 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_PULSE_SHAPE_COMBOS; 37 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_RAN_MULTIPLIER; 38 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_SYNC_CODES; 39 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_UWB_CONFIGS; 40 import static com.android.server.uwb.config.CapabilityParam.CCC_SUPPORTED_VERSIONS; 41 42 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_12; 43 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_24; 44 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_3; 45 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_4; 46 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_6; 47 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_8; 48 import static com.google.uwb.support.ccc.CccParams.CHAPS_PER_SLOT_9; 49 import static com.google.uwb.support.ccc.CccParams.HOPPING_CONFIG_MODE_ADAPTIVE; 50 import static com.google.uwb.support.ccc.CccParams.HOPPING_CONFIG_MODE_CONTINUOUS; 51 import static com.google.uwb.support.ccc.CccParams.HOPPING_CONFIG_MODE_NONE; 52 import static com.google.uwb.support.ccc.CccParams.HOPPING_SEQUENCE_AES; 53 import static com.google.uwb.support.ccc.CccParams.HOPPING_SEQUENCE_DEFAULT; 54 import static com.google.uwb.support.ccc.CccParams.UWB_CHANNEL_5; 55 import static com.google.uwb.support.ccc.CccParams.UWB_CHANNEL_9; 56 57 import com.android.server.uwb.config.ConfigParam; 58 59 import com.google.uwb.support.base.Params; 60 import com.google.uwb.support.ccc.CccProtocolVersion; 61 import com.google.uwb.support.ccc.CccPulseShapeCombo; 62 import com.google.uwb.support.ccc.CccRangingStartedParams; 63 import com.google.uwb.support.ccc.CccSpecificationParams; 64 65 import java.nio.ByteBuffer; 66 import java.nio.ByteOrder; 67 68 /** 69 * CCC decoder 70 */ 71 public class CccDecoder extends TlvDecoder { 72 @Override getParams(TlvDecoderBuffer tlvs, Class<T> paramsType)73 public <T extends Params> T getParams(TlvDecoderBuffer tlvs, Class<T> paramsType) 74 throws IllegalArgumentException { 75 if (CccRangingStartedParams.class.equals(paramsType)) { 76 return (T) getCccRangingStartedParamsFromTlvBuffer(tlvs); 77 } 78 if (CccSpecificationParams.class.equals(paramsType)) { 79 return (T) getCccSpecificationParamsFromTlvBuffer(tlvs); 80 } 81 return null; 82 } 83 isBitSet(int flags, int mask)84 private static boolean isBitSet(int flags, int mask) { 85 return (flags & mask) != 0; 86 } 87 getCccRangingStartedParamsFromTlvBuffer(TlvDecoderBuffer tlvs)88 private CccRangingStartedParams getCccRangingStartedParamsFromTlvBuffer(TlvDecoderBuffer tlvs) { 89 byte[] hopModeKey = tlvs.getByteArray(ConfigParam.HOP_MODE_KEY); 90 int hopModeKeyInt = ByteBuffer.wrap(hopModeKey).order(ByteOrder.LITTLE_ENDIAN).getInt(); 91 return new CccRangingStartedParams.Builder() 92 // STS_Index0 0 - 0x3FFFFFFFF 93 .setStartingStsIndex(tlvs.getInt(ConfigParam.STS_INDEX)) 94 .setHopModeKey(hopModeKeyInt) 95 // UWB_Time0 0 - 0xFFFFFFFFFFFFFFFF UWB_INITIATION_TIME 96 .setUwbTime0(tlvs.getLong(ConfigParam.UWB_TIME0)) 97 // RANGING_INTERVAL = RAN_Multiplier * 96 98 .setRanMultiplier(tlvs.getInt(ConfigParam.RANGING_INTERVAL) / 96) 99 .setSyncCodeIndex(tlvs.getByte(ConfigParam.PREAMBLE_CODE_INDEX)) 100 .build(); 101 } 102 getCccSpecificationParamsFromTlvBuffer(TlvDecoderBuffer tlvs)103 private CccSpecificationParams getCccSpecificationParamsFromTlvBuffer(TlvDecoderBuffer tlvs) { 104 CccSpecificationParams.Builder builder = new CccSpecificationParams.Builder(); 105 byte[] versions = tlvs.getByteArray(CCC_SUPPORTED_VERSIONS); 106 if (versions.length % 2 != 0) { 107 throw new IllegalArgumentException("Invalid supported protocol versions len " 108 + versions.length); 109 } 110 for (int i = 0; i < versions.length; i += 2) { 111 builder.addProtocolVersion(CccProtocolVersion.fromBytes(versions, i)); 112 } 113 byte[] configs = tlvs.getByteArray(CCC_SUPPORTED_UWB_CONFIGS); 114 for (int i = 0; i < configs.length; i++) { 115 builder.addUwbConfig(configs[i]); 116 } 117 byte[] pulse_shape_combos = tlvs.getByteArray(CCC_SUPPORTED_PULSE_SHAPE_COMBOS); 118 for (int i = 0; i < pulse_shape_combos.length; i++) { 119 builder.addPulseShapeCombo(CccPulseShapeCombo.fromBytes(pulse_shape_combos, i)); 120 } 121 builder.setRanMultiplier(tlvs.getInt(CCC_SUPPORTED_RAN_MULTIPLIER)); 122 byte chapsPerslot = tlvs.getByte(CCC_SUPPORTED_CHAPS_PER_SLOT); 123 if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_3)) { 124 builder.addChapsPerSlot(CHAPS_PER_SLOT_3); 125 } 126 if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_4)) { 127 builder.addChapsPerSlot(CHAPS_PER_SLOT_4); 128 } 129 if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_6)) { 130 builder.addChapsPerSlot(CHAPS_PER_SLOT_6); 131 } 132 if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_8)) { 133 builder.addChapsPerSlot(CHAPS_PER_SLOT_8); 134 } 135 if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_9)) { 136 builder.addChapsPerSlot(CHAPS_PER_SLOT_9); 137 } 138 if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_12)) { 139 builder.addChapsPerSlot(CHAPS_PER_SLOT_12); 140 } 141 if (isBitSet(chapsPerslot, CCC_CHAPS_PER_SLOT_24)) { 142 builder.addChapsPerSlot(CHAPS_PER_SLOT_24); 143 } 144 // Don't use TlvDecodeBuffer#getInt() to avoid conversion to little endian. 145 int syncCodes = ByteBuffer.wrap(tlvs.getByteArray(CCC_SUPPORTED_SYNC_CODES)).getInt(); 146 for (int i = 0; i < 32; i++) { 147 if (isBitSet(syncCodes, 1 << i)) { 148 builder.addSyncCode(i + 1); 149 } 150 } 151 byte channels = tlvs.getByte(CCC_SUPPORTED_CHANNELS); 152 if (isBitSet(channels, CCC_CHANNEL_5)) { 153 builder.addChannel(UWB_CHANNEL_5); 154 } 155 if (isBitSet(channels, CCC_CHANNEL_9)) { 156 builder.addChannel(UWB_CHANNEL_9); 157 } 158 byte hoppingConfigModesAndSequences = 159 tlvs.getByte(CCC_SUPPORTED_HOPPING_CONFIG_MODES_AND_SEQUENCES); 160 if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_CONFIG_MODE_NONE)) { 161 builder.addHoppingConfigMode(HOPPING_CONFIG_MODE_NONE); 162 } 163 if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_CONFIG_MODE_CONTINUOUS)) { 164 builder.addHoppingConfigMode(HOPPING_CONFIG_MODE_CONTINUOUS); 165 } 166 if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_CONFIG_MODE_ADAPTIVE)) { 167 builder.addHoppingConfigMode(HOPPING_CONFIG_MODE_ADAPTIVE); 168 } 169 if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_SEQUENCE_AES)) { 170 builder.addHoppingSequence(HOPPING_SEQUENCE_AES); 171 } 172 if (isBitSet(hoppingConfigModesAndSequences, CCC_HOPPING_SEQUENCE_DEFAULT)) { 173 builder.addHoppingSequence(HOPPING_SEQUENCE_DEFAULT); 174 } 175 return builder.build(); 176 } 177 } 178