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)27 constexpr 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