1 /* 2 * Copyright (c) 2011-2015, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation and/or 13 * other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors 16 * may be used to endorse or promote products derived from this software without 17 * specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 #include "BitParameterType.h" 31 #include "BitParameter.h" 32 #include <stdlib.h> 33 #include <sstream> 34 #include "ParameterAccessContext.h" 35 #include "BitParameterBlockType.h" 36 #include "Utility.h" 37 38 #define base CTypeElement 39 40 using std::string; 41 42 CBitParameterType::CBitParameterType(const string &strName) : base(strName) 43 { 44 } 45 46 // CElement 47 string CBitParameterType::getKind() const 48 { 49 return "BitParameter"; 50 } 51 52 // Element properties 53 void CBitParameterType::showProperties(string &strResult) const 54 { 55 base::showProperties(strResult); 56 57 // Bit Pos 58 strResult += "Bit pos: "; 59 strResult += std::to_string(_bitPos); 60 strResult += "\n"; 61 62 // Bit size 63 strResult += "Bit size: "; 64 strResult += std::to_string(_uiBitSize); 65 strResult += "\n"; 66 67 // Max 68 strResult += "Max: "; 69 strResult += std::to_string(_uiMax); 70 strResult += "\n"; 71 } 72 73 // From IXmlSink 74 bool CBitParameterType::fromXml(const CXmlElement &xmlElement, 75 CXmlSerializingContext &serializingContext) 76 { 77 // Pos 78 xmlElement.getAttribute("Pos", _bitPos); 79 80 // Size 81 xmlElement.getAttribute("Size", _uiBitSize); 82 83 // Validate bit pos and size still fit into parent type 84 const CBitParameterBlockType *pBitParameterBlockType = 85 static_cast<const CBitParameterBlockType *>(getParent()); 86 87 size_t uiParentBlockBitSize = pBitParameterBlockType->getSize() * 8; 88 89 if (_bitPos + _uiBitSize > uiParentBlockBitSize) { 90 91 // Range exceeded 92 std::ostringstream strStream; 93 94 strStream << "Pos and Size attributes inconsistent with maximum container element size (" 95 << uiParentBlockBitSize << " bits) for " + getKind(); 96 97 serializingContext.setError(strStream.str()); 98 99 return false; 100 } 101 102 // Max 103 _uiMax = getMaxEncodableValue(); 104 if (xmlElement.getAttribute("Max", _uiMax) && (_uiMax > getMaxEncodableValue())) { 105 106 // Max value exceeded 107 std::ostringstream strStream; 108 109 strStream << "Max attribute inconsistent with maximum encodable size (" 110 << getMaxEncodableValue() << ") for " + getKind(); 111 112 serializingContext.setError(strStream.str()); 113 114 return false; 115 } 116 117 // Base 118 return base::fromXml(xmlElement, serializingContext); 119 } 120 121 // Conversion 122 bool CBitParameterType::toBlackboard(const string &strValue, uint64_t &uiValue, 123 CParameterAccessContext ¶meterAccessContext) const 124 { 125 // Get value 126 uint64_t uiConvertedValue = strtoull(strValue.c_str(), NULL, 0); 127 128 if (uiConvertedValue > _uiMax) { 129 130 // Range exceeded 131 std::ostringstream strStream; 132 133 strStream << "Value " << strValue << " standing out of admitted range ["; 134 135 if (utility::isHexadecimal(strValue)) { 136 137 strStream << "0x0, " 138 << "0x" << std::hex << std::uppercase; 139 } else { 140 141 strStream << "0, "; 142 } 143 strStream << _uiMax << "] for " + getKind(); 144 145 parameterAccessContext.setError(strStream.str()); 146 147 return false; 148 } 149 150 // Do bitwise RMW operation 151 uiValue = (uiValue & ~getMask()) | (uiConvertedValue << _bitPos); 152 153 return true; 154 } 155 156 void CBitParameterType::fromBlackboard(string &strValue, const uint64_t &uiValue, 157 CParameterAccessContext ¶meterAccessContext) const 158 { 159 uint64_t uiConvertedValue = (uiValue & getMask()) >> _bitPos; 160 161 // Format 162 std::ostringstream strStream; 163 164 // Take care of format 165 if (parameterAccessContext.valueSpaceIsRaw() && parameterAccessContext.outputRawFormatIsHex()) { 166 167 strStream << "0x" << std::hex << std::uppercase; 168 } 169 170 strStream << uiConvertedValue; 171 172 strValue = strStream.str(); 173 } 174 175 // Value access 176 // Integer 177 bool CBitParameterType::toBlackboard(uint64_t uiUserValue, uint64_t &uiValue, 178 CParameterAccessContext ¶meterAccessContext) const 179 { 180 if (uiUserValue > _uiMax) { 181 182 parameterAccessContext.setError("Value out of range"); 183 184 return false; 185 } 186 187 // Do bitwise RMW operation 188 uiValue = (uiValue & ~getMask()) | (uiUserValue << _bitPos); 189 190 return true; 191 } 192 193 void CBitParameterType::fromBlackboard(uint32_t &userValue, uint64_t value, 194 CParameterAccessContext & /*ctx*/) const 195 { 196 userValue = static_cast<uint32_t>((value & getMask()) >> _bitPos); 197 } 198 199 // Access from area configuration 200 uint64_t CBitParameterType::merge(uint64_t uiOriginData, uint64_t uiNewData) const 201 { 202 return (uiOriginData & ~getMask()) | (uiNewData & getMask()); 203 } 204 205 // Bit Size 206 size_t CBitParameterType::getBitSize() const 207 { 208 return _uiBitSize; 209 } 210 211 CInstanceConfigurableElement *CBitParameterType::doInstantiate() const 212 { 213 return new CBitParameter(getName(), this); 214 } 215 216 // Max value 217 uint64_t CBitParameterType::getMaxEncodableValue() const 218 { 219 return (uint64_t)-1L >> (8 * sizeof(uint64_t) - _uiBitSize); 220 } 221 222 // Biwise mask 223 uint64_t CBitParameterType::getMask() const 224 { 225 return getMaxEncodableValue() << _bitPos; 226 } 227 228 // Check data has no bit set outside available range 229 bool CBitParameterType::isEncodable(uint64_t uiData) const 230 { 231 size_t uiShift = 8 * sizeof(uiData) - _uiBitSize; 232 233 if (uiShift) { 234 235 // Check high bits are clean 236 return !(uiData >> uiShift); 237 } 238 239 return true; 240 } 241 242 // From IXmlSource 243 void CBitParameterType::toXml(CXmlElement &xmlElement, 244 CXmlSerializingContext &serializingContext) const 245 { 246 // Position 247 xmlElement.setAttribute("Pos", _bitPos); 248 249 // Size 250 xmlElement.setAttribute("Size", _uiBitSize); 251 252 // Maximum 253 xmlElement.setAttribute("Max", _uiMax); 254 255 base::toXml(xmlElement, serializingContext); 256 } 257