1 #pragma once 2 #include <cstdint> 3 #include <stdexcept> 4 #include <string_view> 5 6 namespace gpioplus 7 { 8 namespace utility 9 { 10 namespace aspeed 11 { 12 13 /** @brief Converts an aspeed gpio label name into an offset usable 14 * by a gpioplus line. 15 * Ex. GPION3 -> nameToOffset("N3") -> 107 16 * 17 * NOTE: This function is constexpr, but uses exceptions for error 18 * cases. If you want compile time guarantees of validity, make sure 19 * you assign to a constexpr lvalue. Otherwise the error will be 20 * resolved at runtime. 21 * Ex. constexpr uint32_t offset = nameToOffset("A7"); 22 * 23 * @param[in] name - The gpio chip which provides the events 24 * @throws std::logic_error when provided an invalid name. 25 * @return 26 */ nameToOffset(std::string_view name)27constexpr uint32_t nameToOffset(std::string_view name) 28 { 29 // Validate the name [A-Z]+[0-9] 30 if (name.length() < 2) 31 { 32 throw std::logic_error("GPIO name is too short"); 33 } 34 35 char octal = name[name.length() - 1]; 36 if (octal < '0' || octal > '7') 37 { 38 throw std::logic_error("GPIO name must end with an octal"); 39 } 40 41 auto letters = name.substr(0, name.length() - 1); 42 for (auto letter : letters) 43 { 44 if (letter < 'A' || letter > 'Z') 45 { 46 throw std::logic_error("GPIO name must start with letters"); 47 } 48 } 49 50 // Limit the gpio to reasonable values 51 // Current chips have no more than AB7 or 224 gpios 52 if (name.length() > 3 || (name.length() == 3 && name[0] != 'A')) 53 { 54 throw std::logic_error("GPIO name probably not valid"); 55 } 56 57 uint32_t offset = 0; 58 for (auto letter : letters) 59 { 60 offset = offset * 26 + (letter - 'A') + 1; 61 } 62 offset = (offset - 1) * 8 + (octal - '0'); 63 return offset; 64 } 65 66 } // namespace aspeed 67 } // namespace utility 68 } // namespace gpioplus 69