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