File: GpioUtils

Details

File: GpioUtils.cs
Date: Thu, Mar 7, 2019
using System;
using System.Text;
using System.IO;
using System.Collections.Generic;
using System.Runtime.InteropServices;

/// +------------------------------------------------------------------------------------------------------------------------------+
/// |                                                   TERMS OF USE: MIT License                                                  |
/// +------------------------------------------------------------------------------------------------------------------------------|
/// |Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation    |
/// |files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,    |
/// |modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
/// |is furnished to do so, subject to the following conditions:                                                                   |
/// |                                                                                                                              |
/// |The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
/// |                                                                                                                              |
/// |THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE          |
/// |WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR         |
/// |COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,   |
/// |ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                         |
/// +------------------------------------------------------------------------------------------------------------------------------+

namespace BBBCSIO
{
    /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
    /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
    /// <summary>
    /// Provides Tools and Utilities for BBB GPIO's
    /// </summary>
    /// <history>
    ///    28 Aug 14  Cynic - Started
    /// </history>
    public static class GpioUtils
    {
        public const string GPIOENUM_PREFIX = "GPIO_";

        // used for external file open calls
        const int O_RDONLY = 0x0;
        const int O_NONBLOCK = 0x0004;

        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the name (+full path) to a sysfs event file which matches the input
        /// name. The input name will have been set in the Device Tree when the GPIO 
        /// was configured to present interrupts. There can be multiple GPIOs reporting
        /// back through any one event device. The gpio which triggered the event
        /// can be differentiated by the "linux,code" field set on the gpio in the 
        /// Device Tree. To really understand what is going on here you would be
        /// well advised to read the documenation.
        /// 
        /// Note: a device tree node with a label of BBBCSIO_GPIOs will be named something
        ///       like BBBCSIO_GPIOs.7 in the device. The kernel tacks the .7 (or some other
        ///       digit on at boot time and it refers to the order the driver was loaded.
        ///       Since this digit could change, we strip off everything from the input name
        ///       after the last '.' character. We match based on the label!!!
        /// 
        /// </summary>
        /// <returns>The matching device event filename or null for fail</returns>
        /// <param name="nameToLookFOr">the device tree node label which forms the device name (see Note above)</param>
        /// <history>
        ///    28 Aug 14  Cynic - Originally written
        /// </history>
        public static string FindNamedEventDevice(string nameToLookFor)
        {
            string cleanedName = null;
            string deviceName = null;

            if ((nameToLookFor == null) || (nameToLookFor.Length == 0))    return null;

            // get all the event devices. there will be keyboards and mice etc 
            // in here as well as a gpio events (or maybe more than one)
            List<string> deviceList = GetEventDevices();
            if (deviceList.Count == 0) return null;

            // for each device file
            foreach (string deviceFileName in deviceList)
            {
                // get the name from each event device
                deviceName = GetNameFromDevice(deviceFileName);
                if ((deviceName == null) || (deviceName.Length == 0)) continue;
                // clean off the trailing .<digit>
                int lastDotIndex = deviceName.LastIndexOf (".");
                if (lastDotIndex > 0)
                {
                    cleanedName = deviceName.Substring (0, lastDotIndex);
                } else
                {
                    // not found
                    cleanedName = deviceName;
                }
                // now test
                if (cleanedName == nameToLookFor)
                {
                    // found it, return it
                    return deviceFileName;                        
                }
            }
            return null;
        }

        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets the name from a device. We use an external ioctl() call to do this
        /// </summary>
        /// <param name="deviceFileName">the file name for the device</param>
        /// <returns>>The name of the device or null for not found</returns>
        /// <history>
        ///    28 Aug 14  Cynic - Originally written
        /// </history>
        private static string GetNameFromDevice(string deviceFileName)
        {
            int retVal = -1;
            int fd = -1;

            // this is a code in a specific format required
            // by the event device and is passed through as 
            // by the ioctl call 
            // (2 <<30) | (255<<16) | ('E'<<8) | (6<<0);
            int requestVAL = unchecked((int)0x80ff4506);

            // we get our name back in this
            StringBuilder eventName = new StringBuilder (256);

            // sanity check
            if ((deviceFileName == null) || (deviceFileName.Length == 0)) return null;

            try
            {
                // we open the file. We have to have an open file descriptor
                // note this is an external call. It has to be because the 
                // ioctl needs an open file descriptor it can use
                fd = ExternalFileOpen(deviceFileName, O_RDONLY|O_NONBLOCK);
                if(fd <= 0)
                {
                    throw new Exception("Could not open file:" + deviceFileName);
                }
                // this is an external call to the libc.so.6 library
                retVal = ExternalIoCtl(fd, requestVAL, eventName);
                // did the call succeed?
                if(retVal < 0)
                {
                    // it failed
                    throw new Exception("Fetch of name from device " + deviceFileName + " failed");
                }
                // this is 
                ExternalFileClose(fd);
                // return the event name
                return eventName.ToString();
            }
            finally
            {
                // we have to close the file descriptor
                if(fd > 0) ExternalFileClose(fd);
                fd = -1;
            }

        }

        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets a list of all event devices. These are the device files which
        /// expose sysfs events to userspace. Never returns null.
        /// </summary>
        /// <returns>A list of the event files (full path) or empty list for not found</returns>
        /// <history>
        ///    28 Aug 14  Cynic - Originally written
        /// </history>
        public static List<string> GetEventDevices()
        {
            List<string> outList = new List<string>();
            string patternToMatch = BBBDefinitions.SYSFS_EVENTFILEBASENAME+"*";
            foreach (string fileName in Directory.GetFiles(BBBDefinitions.SYSFS_EVENTDIR, patternToMatch))
            {
                outList.Add (fileName);
            }
            return outList;
        }

        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Converts a GpioID to an integer value. Will not accept a gpioID of 
        /// Gpio.GPIO_NONE or GpioEnum.GPIO_SYSEVENT
        /// </summary>
        /// <param name="gpioIDIn">The gpio we open the port on</param>
        /// <history>
        ///    28 Aug 14  Cynic - Originally written
        /// </history>
        public static int GpioIDToInt(GpioEnum gpioIDIn)
        {
            if (gpioIDIn == GpioEnum.GPIO_NONE) 
            {
                throw new Exception ("Invalid Gpio : " + gpioIDIn.ToString ());
            }

            // return it as an integer
            return Convert.ToInt32(GpioIDToString(gpioIDIn));
        }

        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Converts a GpioID to a numeric string value. Will not accept a gpioID of 
        /// Gpio.GPIO_NONE or GpioEnum.GPIO_SYSEVENT
        /// </summary>
        /// <param name="gpioIDIn">The gpio we open the port on</param>
        /// <returns>>the GPIO as a string</returns>
        /// <history>
        ///    28 Aug 14  Cynic - Originally written
        /// </history>
        public static string GpioIDToString(GpioEnum gpioIDIn)
        {
            if (gpioIDIn == GpioEnum.GPIO_NONE) 
            {
                throw new Exception ("Invalid Gpio : " + gpioIDIn.ToString ());
            }

            // strip out non digits - want to do this fast so no regex
            // or cycling through the string testing every char.
            return gpioIDIn.ToString().Replace(GPIOENUM_PREFIX, "");
        }                

        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets a GpioConfig dictionary which uses the RegisterAddress of the pin
        /// as a key. Note the RegisterAddress is Base+RegisterOffset. Never returns
        /// null.
        /// </summary>
        /// <returns>A dictionary of GpioConfig objects indexed by RegisterAddress</returns>
        /// <history>
        ///    28 Aug 14  Cynic  Originally written
        /// </history>
        public static Dictionary<int, GpioConfig> GetRegisterAddressDictionary()
        {
            // build the dictionary
            Dictionary<int, GpioConfig> outDict = new Dictionary<int, GpioConfig>();

            // get all known pin to Gpio correlations
            List<GpioConfig> pin2GpioList = BuildAllKnownGpioConfigObjects();

            // add to the dictionary
            foreach (GpioConfig pin2GpioObj in pin2GpioList)
            {
                outDict.Add (BBBDefinitions.PINMUX_BASE_ADDRESS + pin2GpioObj.PinmuxRegisterOffset, pin2GpioObj);
            }
            return outDict;
        }

        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets a GpioConfig object for a given gpio object. NOTE when the 
        /// GpioConfig object is instantiated it acesses system information
        /// for things like mux pin number and usage in the pinmux pins table
        /// </summary>
        /// <returns>>the GpioConfig object or a dummy (GpioEnum.GPIO_NONE) for fail</returns>
        /// <history>
        ///    28 Aug 14  Cynic  Originally written
        /// </history>
        public static GpioConfig GetGpioConfigForGpio(GpioEnum gpioIn)
        {
            switch (gpioIn)
            {
                case GpioEnum.GPIO_38:
                    return new GpioConfig(8, 3, 0x818, 38, GpioEnum.GPIO_38);
                case GpioEnum.GPIO_39:
                    return new GpioConfig(8, 4, 0x81C, 39, GpioEnum.GPIO_39);
                case GpioEnum.GPIO_34:
                    return new GpioConfig(8, 5, 0x808, 34, GpioEnum.GPIO_34);
                case GpioEnum.GPIO_35:
                    return new GpioConfig(8, 6, 0x80C, 35, GpioEnum.GPIO_35);
                case GpioEnum.GPIO_66:
                    return new GpioConfig(8, 7, 0x890, 66, GpioEnum.GPIO_66);
                case GpioEnum.GPIO_67:
                    return new GpioConfig(8, 8, 0x894, 67, GpioEnum.GPIO_67);
                case GpioEnum.GPIO_69:
                    return new GpioConfig(8, 9, 0x89C, 69, GpioEnum.GPIO_69);
                case GpioEnum.GPIO_68:
                    return new GpioConfig(8, 10, 0x898, 68, GpioEnum.GPIO_68);
                case GpioEnum.GPIO_45:
                    return new GpioConfig(8, 11, 0x834, 45, GpioEnum.GPIO_45);
                case GpioEnum.GPIO_44:
                    return new GpioConfig(8, 12, 0x830, 44, GpioEnum.GPIO_44);
                case GpioEnum.GPIO_23:
                    return new GpioConfig(8, 13, 0x824, 23, GpioEnum.GPIO_23);
                case GpioEnum.GPIO_26:
                    return new GpioConfig(8, 14, 0x828, 26, GpioEnum.GPIO_26);
                case GpioEnum.GPIO_47:
                    return new GpioConfig(8, 15, 0x83C, 47, GpioEnum.GPIO_47);
                case GpioEnum.GPIO_46:
                    return new GpioConfig(8, 16, 0x838, 46, GpioEnum.GPIO_46);
                case GpioEnum.GPIO_27:
                    return new GpioConfig(8, 17, 0x82C, 27, GpioEnum.GPIO_27);
                case GpioEnum.GPIO_65:
                    return new GpioConfig(8, 18, 0x88C, 65, GpioEnum.GPIO_65);
                case GpioEnum.GPIO_22:
                    return new GpioConfig(8, 19, 0x820, 22, GpioEnum.GPIO_22);
                case GpioEnum.GPIO_63:
                    return new GpioConfig(8, 20, 0x884, 63, GpioEnum.GPIO_63);
                case GpioEnum.GPIO_62:
                    return new GpioConfig(8, 21, 0x880, 62, GpioEnum.GPIO_62);
                case GpioEnum.GPIO_37:
                    return new GpioConfig(8, 22, 0x814, 37, GpioEnum.GPIO_37);
                case GpioEnum.GPIO_36:
                    return new GpioConfig(8, 23, 0x810, 36, GpioEnum.GPIO_36);
                case GpioEnum.GPIO_33:
                    return new GpioConfig(8, 24, 0x804, 33, GpioEnum.GPIO_33);
                case GpioEnum.GPIO_32:
                    return new GpioConfig(8, 25, 0x800, 32, GpioEnum.GPIO_32);
                case GpioEnum.GPIO_61:
                    return new GpioConfig(8, 26, 0x87C, 61, GpioEnum.GPIO_61);
                case GpioEnum.GPIO_86:
                    return new GpioConfig(8, 27, 0x8E0, 86, GpioEnum.GPIO_86);
                case GpioEnum.GPIO_88:
                    return new GpioConfig(8, 28, 0x8E8, 88, GpioEnum.GPIO_88);
                case GpioEnum.GPIO_87:
                    return new GpioConfig(8, 29, 0x8E4, 87, GpioEnum.GPIO_87);
                case GpioEnum.GPIO_89:
                    return new GpioConfig(8, 30, 0x8EC, 89, GpioEnum.GPIO_89);
                case GpioEnum.GPIO_10:
                    return new GpioConfig(8, 31, 0x8D8, 10, GpioEnum.GPIO_10);
                case GpioEnum.GPIO_11:
                    return new GpioConfig(8, 32, 0x8DC, 11, GpioEnum.GPIO_11);
                case GpioEnum.GPIO_9:
                    return new GpioConfig(8, 33, 0x8D4, 9, GpioEnum.GPIO_9);
                case GpioEnum.GPIO_81:
                    return new GpioConfig(8, 34, 0x8CC, 81, GpioEnum.GPIO_81);
                case GpioEnum.GPIO_8:
                    return new GpioConfig(8, 35, 0x8D0, 8, GpioEnum.GPIO_8);
                case GpioEnum.GPIO_80:
                    return new GpioConfig(8, 36, 0x8C8, 80, GpioEnum.GPIO_80);
                case GpioEnum.GPIO_78:
                    return new GpioConfig(8, 37, 0x8C0, 78, GpioEnum.GPIO_78);
                case GpioEnum.GPIO_79:
                    return new GpioConfig(8, 38, 0x8C4, 79, GpioEnum.GPIO_79);
                case GpioEnum.GPIO_76:
                    return new GpioConfig(8, 39, 0x8B8, 76, GpioEnum.GPIO_76);
                case GpioEnum.GPIO_77:
                    return new GpioConfig(8, 40, 0x8BC, 77, GpioEnum.GPIO_77);
                case GpioEnum.GPIO_74:
                    return new GpioConfig(8, 41, 0x8B0, 74, GpioEnum.GPIO_74);
                case GpioEnum.GPIO_75:
                    return new GpioConfig(8, 42, 0x8B4, 75, GpioEnum.GPIO_75);
                case GpioEnum.GPIO_72:
                    return new GpioConfig(8, 43, 0x8A8, 72, GpioEnum.GPIO_72);
                case GpioEnum.GPIO_73:
                    return new GpioConfig(8, 44, 0x8AC, 73, GpioEnum.GPIO_73);
                case GpioEnum.GPIO_70:
                    return new GpioConfig(8, 45, 0x8A0, 70, GpioEnum.GPIO_70);
                case GpioEnum.GPIO_71:
                    return new GpioConfig(8, 46, 0x8A4, 71, GpioEnum.GPIO_71);
                case GpioEnum.GPIO_30:
                    return new GpioConfig(9, 11, 0x870, 30, GpioEnum.GPIO_30);
                case GpioEnum.GPIO_60:
                    return new GpioConfig(9, 12, 0x878, 60, GpioEnum.GPIO_60);
                case GpioEnum.GPIO_31:
                    return new GpioConfig(9, 13, 0x874, 31, GpioEnum.GPIO_31);
                case GpioEnum.GPIO_50:
                    return new GpioConfig(9, 14, 0x848, 50, GpioEnum.GPIO_50);
                case GpioEnum.GPIO_48:
                    return new GpioConfig(9, 15, 0x840, 48, GpioEnum.GPIO_48);
                case GpioEnum.GPIO_51:
                    return new GpioConfig(9, 16, 0x84C, 51, GpioEnum.GPIO_51);
                case GpioEnum.GPIO_5:
                    return new GpioConfig(9, 17, 0x95C, 5, GpioEnum.GPIO_5);
                case GpioEnum.GPIO_4:
                    return new GpioConfig(9, 18, 0x958, 4, GpioEnum.GPIO_4);
                case GpioEnum.GPIO_13:
                    return new GpioConfig(9, 19, 0x97C, 13, GpioEnum.GPIO_13);
                case GpioEnum.GPIO_12:
                    return new GpioConfig(9, 20, 0x978, 12, GpioEnum.GPIO_12);
                case GpioEnum.GPIO_3:
                    return new GpioConfig(9, 21, 0x954, 3, GpioEnum.GPIO_3);
                case GpioEnum.GPIO_2:
                    return new GpioConfig(9, 22, 0x950, 2, GpioEnum.GPIO_2);
                case GpioEnum.GPIO_49:
                    return new GpioConfig(9, 23, 0x844, 49, GpioEnum.GPIO_49);
                case GpioEnum.GPIO_15:
                    return new GpioConfig(9, 24, 0x984, 15, GpioEnum.GPIO_15);
                case GpioEnum.GPIO_117:
                    return new GpioConfig(9, 25, 0x9AC, 117, GpioEnum.GPIO_117);
                case GpioEnum.GPIO_14:
                    return new GpioConfig(9, 26, 0x980, 14, GpioEnum.GPIO_14);
                case GpioEnum.GPIO_115:
                    return new GpioConfig(9, 27, 0x9A4, 115, GpioEnum.GPIO_115);
                case GpioEnum.GPIO_113:
                    return new GpioConfig(9, 28, 0x99C, 113, GpioEnum.GPIO_113);
                case GpioEnum.GPIO_111:
                    return new GpioConfig(9, 29, 0x994, 111, GpioEnum.GPIO_111);
                case GpioEnum.GPIO_112:
                    return new GpioConfig(9, 30, 0x998, 112, GpioEnum.GPIO_112);
                case GpioEnum.GPIO_110:
                    return new GpioConfig(9, 31, 0x990, 110, GpioEnum.GPIO_110);
                case GpioEnum.GPIO_20:
                    return new GpioConfig(9, 41, 0x9B4, 20, GpioEnum.GPIO_20);
                case GpioEnum.GPIO_7:
                    return new GpioConfig(9, 42, 0x964, 7, GpioEnum.GPIO_7);
                default:
                    return new GpioConfig();
            }
        }

        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Get all known GpioConfig objects. These are returned with hard coded 
        /// contents based on the documentation and not fully filled in with 
        /// information derived from the system. Never returns NULL.
        /// </summary>
        /// <returns>>a list of all known GpioConfig objects</returns>
        /// <history>
        ///    28 Aug 14  Cynic  Originally written
        /// </history>
        public static List<GpioConfig> BuildAllKnownGpioConfigObjects()
        {
            List<GpioConfig> outList = new List<GpioConfig> ();

            // run down through the GpioEnum and create one for every
            // value it contains. 
            foreach (GpioEnum gpioVal in (GpioEnum[])Enum.GetValues(typeof(GpioEnum)))
            {
                // never do this one
                if (gpioVal == GpioEnum.GPIO_NONE) continue;
                outList.Add(GetGpioConfigForGpio(gpioVal));
            }
            return outList;

/* slightly less old way
            outList.Add(new GpioConfig(8, 3, 0x818, 38,  GpioEnum.GPIO_38));
            outList.Add(new GpioConfig(8, 4, 0x81C, 39,  GpioEnum.GPIO_39));
            outList.Add(new GpioConfig(8, 5, 0x808, 34,  GpioEnum.GPIO_34));
            outList.Add(new GpioConfig(8, 6, 0x80C, 35,  GpioEnum.GPIO_35));
            outList.Add(new GpioConfig(8, 7, 0x890, 66,  GpioEnum.GPIO_66));
            outList.Add(new GpioConfig(8, 8, 0x894, 67,  GpioEnum.GPIO_67));
            outList.Add(new GpioConfig(8, 9, 0x89C, 69,  GpioEnum.GPIO_69));
            outList.Add(new GpioConfig(8, 10, 0x898, 68,  GpioEnum.GPIO_68));
            outList.Add(new GpioConfig(8, 11, 0x834, 45,  GpioEnum.GPIO_45));
            outList.Add(new GpioConfig(8, 12, 0x830, 44,  GpioEnum.GPIO_44));
            outList.Add(new GpioConfig(8, 13, 0x824, 23,  GpioEnum.GPIO_23));
            outList.Add(new GpioConfig(8, 14, 0x828, 26,  GpioEnum.GPIO_26));
            outList.Add(new GpioConfig(8, 15, 0x83C, 47,  GpioEnum.GPIO_47));
            outList.Add(new GpioConfig(8, 16, 0x838, 46,  GpioEnum.GPIO_46));
            outList.Add(new GpioConfig(8, 17, 0x82C, 27,  GpioEnum.GPIO_27));
            outList.Add(new GpioConfig(8, 18, 0x88C, 65,  GpioEnum.GPIO_65));
            outList.Add(new GpioConfig(8, 19, 0x820, 22,  GpioEnum.GPIO_22));
            outList.Add(new GpioConfig(8, 20, 0x884, 63,  GpioEnum.GPIO_63));
            outList.Add(new GpioConfig(8, 21, 0x880, 62,  GpioEnum.GPIO_62));
            outList.Add(new GpioConfig(8, 22, 0x814, 37,  GpioEnum.GPIO_37));
            outList.Add(new GpioConfig(8, 23, 0x810, 36,  GpioEnum.GPIO_36));
            outList.Add(new GpioConfig(8, 24, 0x804, 33,  GpioEnum.GPIO_33));
            outList.Add(new GpioConfig(8, 25, 0x800, 32,  GpioEnum.GPIO_32));
            outList.Add(new GpioConfig(8, 26, 0x87C, 61,  GpioEnum.GPIO_61));
            outList.Add(new GpioConfig(8, 27, 0x8E0, 86,  GpioEnum.GPIO_86));
            outList.Add(new GpioConfig(8, 28, 0x8E8, 88,  GpioEnum.GPIO_88));
            outList.Add(new GpioConfig(8, 29, 0x8E4, 87,  GpioEnum.GPIO_87));
            outList.Add(new GpioConfig(8, 30, 0x8EC, 89,  GpioEnum.GPIO_89));
            outList.Add(new GpioConfig(8, 31, 0x8D8, 10,  GpioEnum.GPIO_10));
            outList.Add(new GpioConfig(8, 32, 0x8DC, 11,  GpioEnum.GPIO_11));
            outList.Add(new GpioConfig(8, 33, 0x8D4, 9,  GpioEnum.GPIO_9));
            outList.Add(new GpioConfig(8, 34, 0x8CC, 81,  GpioEnum.GPIO_81));
            outList.Add(new GpioConfig(8, 35, 0x8D0, 8,  GpioEnum.GPIO_8));
            outList.Add(new GpioConfig(8, 36, 0x8C8, 80,  GpioEnum.GPIO_80));
            outList.Add(new GpioConfig(8, 37, 0x8C0, 78,  GpioEnum.GPIO_78));
            outList.Add(new GpioConfig(8, 38, 0x8C4, 79,  GpioEnum.GPIO_79));
            outList.Add(new GpioConfig(8, 39, 0x8B8, 76,  GpioEnum.GPIO_76));
            outList.Add(new GpioConfig(8, 40, 0x8BC, 77,  GpioEnum.GPIO_77));
            outList.Add(new GpioConfig(8, 41, 0x8B0, 74,  GpioEnum.GPIO_74));
            outList.Add(new GpioConfig(8, 42, 0x8B4, 75,  GpioEnum.GPIO_75));
            outList.Add(new GpioConfig(8, 43, 0x8A8, 72,  GpioEnum.GPIO_72));
            outList.Add(new GpioConfig(8, 44, 0x8AC, 73,  GpioEnum.GPIO_73));
            outList.Add(new GpioConfig(8, 45, 0x8A0, 70,  GpioEnum.GPIO_70));
            outList.Add(new GpioConfig(8, 46, 0x8A4, 71,  GpioEnum.GPIO_71));
            outList.Add(new GpioConfig(9, 11, 0x870, 30,  GpioEnum.GPIO_30));
            outList.Add(new GpioConfig(9, 12, 0x878, 60,  GpioEnum.GPIO_60));
            outList.Add(new GpioConfig(9, 13, 0x874, 31,  GpioEnum.GPIO_31));
            outList.Add(new GpioConfig(9, 14, 0x848, 50,  GpioEnum.GPIO_50));
            outList.Add(new GpioConfig(9, 15, 0x840, 48,  GpioEnum.GPIO_48));
            outList.Add(new GpioConfig(9, 16, 0x84C, 51,  GpioEnum.GPIO_51));
            outList.Add(new GpioConfig(9, 17, 0x95C, 5,  GpioEnum.GPIO_5));
            outList.Add(new GpioConfig(9, 18, 0x958, 4,  GpioEnum.GPIO_4));
            outList.Add(new GpioConfig(9, 19, 0x97C, 13,  GpioEnum.GPIO_13));
            outList.Add(new GpioConfig(9, 20, 0x978, 12,  GpioEnum.GPIO_12));
            outList.Add(new GpioConfig(9, 21, 0x954, 3,  GpioEnum.GPIO_3));
            outList.Add(new GpioConfig(9, 22, 0x950, 2,  GpioEnum.GPIO_2));
            outList.Add(new GpioConfig(9, 23, 0x844, 49,  GpioEnum.GPIO_49));
            outList.Add(new GpioConfig(9, 24, 0x984, 15,  GpioEnum.GPIO_15));
            outList.Add(new GpioConfig(9, 25, 0x9AC, 117,  GpioEnum.GPIO_117));
            outList.Add(new GpioConfig(9, 26, 0x980, 14,  GpioEnum.GPIO_14));
            outList.Add(new GpioConfig(9, 27, 0x9A4, 115,  GpioEnum.GPIO_115));
            outList.Add(new GpioConfig(9, 28, 0x99C, 113,  GpioEnum.GPIO_113));
            outList.Add(new GpioConfig(9, 29, 0x994, 111,  GpioEnum.GPIO_111));
            outList.Add(new GpioConfig(9, 30, 0x998, 112,  GpioEnum.GPIO_112));
            outList.Add(new GpioConfig(9, 31, 0x990, 110,  GpioEnum.GPIO_110));
            outList.Add(new GpioConfig(9, 41, 0x9B4, 20,  GpioEnum.GPIO_20));
            outList.Add(new GpioConfig(9, 42, 0x964, 7,  GpioEnum.GPIO_7));
 */

/* older method with mode usage labels
            // add the Pins for P8 header
            outList.Add(new GpioConfig(8,3,"GPMC_AD6",0x818,"gpmc_ad6","mmc1_dat6","","","","","","*gpio1_6","emmc"));
            outList.Add(new GpioConfig(8,4,"GPMC_AD7",0x81C,"gpmc_ad7","mmc1_dat7","","","","","","*gpio1_7","emmc"));
            outList.Add(new GpioConfig(8,5,"GPMC_AD2",0x808,"gpmc_ad2","mmc1_dat2","","","","","","*gpio1_2","emmc"));
            outList.Add(new GpioConfig(8,6,"GPMC_AD3",0x80C,"gpmc_ad3","mmc1_dat3","","","","","","*gpio1_3","emmc"));
            outList.Add(new GpioConfig(8,7,"GPMC_ADVn_ALE",0x890,"gpmc_advn_ale","","timer4","","","","","*gpio2_2",""));
            outList.Add(new GpioConfig(8,8,"GPMC_OEn_REn",0x894,"gpmc_oen_ren","","timer7","","","","","*gpio2_3",""));
            outList.Add(new GpioConfig(8,9,"GPMC_BEn0_CLE",0x89C,"gpmc_be0n_cle","","timer5","","","","","*gpio2_5",""));
            outList.Add(new GpioConfig(8,10,"GPMC_WEn",0x898,"gpmc_wen","","timer6","","","","","*gpio2_4",""));
            outList.Add(new GpioConfig(8,11,"GPMC_AD13",0x834,"gpmc_ad13","lcd_data18","mmc1_dat5","mmc2_dat1","eQEP2B_in","pr1_mii0_txd1","pr1_pru0_pru_r30_15","*gpio1_13",""));
            outList.Add(new GpioConfig(8,12,"GPMC_AD12",0x830,"gpmc_ad12","lcd_data19","mmc1_dat4","mmc2_dat0","eQEP2A_in","pr1_mii0_txd2","pr1_pru0_pru_r30_14","*gpio1_12",""));
            outList.Add(new GpioConfig(8,13,"GPMC_AD9",0x824,"gpmc_ad9","lcd_data22","mmc1_dat1","mmc2_dat5","ehrpwm2B","pr1_mii0_col","","*gpio0_23",""));
            outList.Add(new GpioConfig(8,14,"GPMC_AD10",0x828,"gpmc_ad10","lcd_data21","mmc1_dat2","mmc2_dat6","ehrpwm2_tripzone_input","pr1_mii0_txen","","*gpio0_26",""));
            outList.Add(new GpioConfig(8,15,"GPMC_AD15",0x83C,"gpmc_ad15","lcd_data16","mmc1_dat7","mmc2_dat3","eQEP2_strobe","pr1_ecap0_ecap_capin_apwm_o","pr1_pru0_pru_r31_15","*gpio1_15",""));
            outList.Add(new GpioConfig(8,16,"GPMC_AD14",0x838,"gpmc_ad14","lcd_data17","mmc1_dat6","mmc2_dat2","eQEP2_index","pr1_mii0_txd0","pr1_pru0_pru_r31_14","*gpio1_14",""));
            outList.Add(new GpioConfig(8,17,"GPMC_AD11",0x82C,"gpmc_ad11","lcd_data20","mmc1_dat3","mmc2_dat7","ehrpwm0_synco","pr1_mii0_txd3","","*gpio0_27",""));
            outList.Add(new GpioConfig(8,18,"GPMC_CLK",0x88C,"gpmc_clk","lcd_memory_clk","gpmc_wait1","mmc2_clk","pr1_mii1_crs","pr1_mdio_mdclk","mcasp0_fsr","*gpio2_1",""));
            outList.Add(new GpioConfig(8,19,"GPMC_AD8",0x820,"gpmc_ad8","lcd_data23","mmc1_dat0","mmc2_dat4","ehrpwm2A","pr1_mii_mt0_clk","","*gpio0_22",""));
            outList.Add(new GpioConfig(8,20,"GPMC_CSn2",0x884,"gpmc_csn2","gpmc_be1n","mmc1_cmd","pr1_edio_data_in7","pr1_edio_data_out7","pr1_pru1_pru_r30_13","pr1_pru1_pru_r31_13","*gpio1_31","emmc"));
            outList.Add(new GpioConfig(8,21,"GPMC_CSn1",0x880,"gpmc_csn1","gpmc_clk","mmc1_clk","pr1_edio_data_in6","pr1_edio_data_out6","pr1_pru1_pru_r30_12","pr1_pru1_pru_r31_12","*gpio1_30","emmc"));
            outList.Add(new GpioConfig(8,22,"GPMC_AD5",0x814,"gpmc_ad5","mmc1_dat5","","","","","","*gpio1_5","emmc"));
            outList.Add(new GpioConfig(8,23,"GPMC_AD4",0x810,"gpmc_ad4","mmc1_dat4","","","","","","*gpio1_4","emmc"));
            outList.Add(new GpioConfig(8,24,"GPMC_AD1",0x804,"gpmc_ad1","mmc1_dat1","","","","","","*gpio1_1","emmc"));
            outList.Add(new GpioConfig(8,25,"GPMC_AD0",0x800,"gpmc_ad0","mmc1_dat0","","","","","","*gpio1_0","emmc"));
            outList.Add(new GpioConfig(8,26,"GPMC_CSn0",0x87C,"gpmc_csn0","","","","","","","*gpio1_29",""));
            outList.Add(new GpioConfig(8,27,"LCD_VSYNC",0x8E0,"lcd_vsync","gpmc_a8","gpmc_a1","pr1_edio_data_in2","pr1_edio_data_out2","pr1_pru1_pru_r30_8","pr1_pru1_pru_r31_8","*gpio2_22","hdmi"));
            outList.Add(new GpioConfig(8,28,"LCD_PCLK",0x8E8,"lcd_pclk","gpmc_a10","pr1_mii0_crs","pr1_edio_data_in4","pr1_edio_data_out4","pr1_pru1_pru_r30_10","pr1_pru1_pru_r31_10","*gpio2_24","hdmi"));
            outList.Add(new GpioConfig(8,29,"LCD_HSYNC",0x8E4,"lcd_hsync","gpmc_a9","gpmc_a2","pr1_edio_data_in3","pr1_edio_data_out3","pr1_pru1_pru_r30_9","pr1_pru1_pru_r31_9","*gpio2_23","hdmi"));
            outList.Add(new GpioConfig(8,30,"LCD_AC_BIAS_EN",0x8EC,"lcd_ac_bias_en","gpmc_a11","pr1_mii1_crs","pr1_edio_data_in5","pr1_edio_data_out5","pr1_pru1_pru_r30_11","pr1_pru1_pru_r31_11","*gpio2_25","hdmi"));
            outList.Add(new GpioConfig(8,31,"LCD_DATA14",0x8D8,"lcd_data14","gpmc_a18","eQEP1_index","mcasp0_axr1","uart5_rxd","pr1_mii_mr0_clk","uart5_ctsn","*gpio0_10","hdmi"));
            outList.Add(new GpioConfig(8,32,"LCD_DATA15",0x8DC,"lcd_data15","gpmc_a19","eQEP1_strobe","mcasp0_ahclkx","mcasp0_axr3","pr1_mii0_rxdv","uart5_rtsn","*gpio0_11","hdmi"));
            outList.Add(new GpioConfig(8,33,"LCD_DATA13",0x8D4,"lcd_data13","gpmc_a17","eQEP1B_in","mcasp0_fsr","mcasp0_axr3","pr1_mii0_rxer","uart4_rtsn","*gpio0_9","hdmi"));
            outList.Add(new GpioConfig(8,34,"LCD_DATA11",0x8CC,"lcd_data11","gpmc_a15","ehrpwm1B","mcasp0_ahclkr","mcasp0_axr2","pr1_mii0_rxd0","uart3_rtsn","*gpio2_17","hdmi"));
            outList.Add(new GpioConfig(8,35,"LCD_DATA12",0x8D0,"lcd_data12","gpmc_a16","eQEP1A_in","mcasp0_aclkr","mcasp0_axr2","pr1_mii0_rxlink","uart4_ctsn","*gpio0_8","hdmi"));
            outList.Add(new GpioConfig(8,36,"LCD_DATA10",0x8C8,"lcd_data10","gpmc_a14","ehrpwm1A","mcasp0_axr0","","pr1_mii0_rxd1","uart3_ctsn","*gpio2_16","hdmi"));
            outList.Add(new GpioConfig(8,37,"LCD_DATA8",0x8C0,"lcd_data8","gpmc_a12","ehrpwm1_tripzone_input","mcasp0_aclkx","uart5_txd","pr1_mii0_rxd3","uart2_ctsn","*gpio2_14","hdmi"));
            outList.Add(new GpioConfig(8,38,"LCD_DATA9",0x8C4,"lcd_data9","gpmc_a13","ehrpwm0_synco","mcasp0_fsx","uart5_rxd","pr1_mii0_rxd2","uart2_rtsn","*gpio2_15","hdmi"));
            outList.Add(new GpioConfig(8,39,"LCD_DATA6",0x8B8,"lcd_data6","gpmc_a6","pr1_edio_data_in6","eQEP2_index","pr1_edio_data_out6","pr1_pru1_pru_r30_6","pr1_pru1_pru_r31_6","*gpio2_12","hdmi"));
            outList.Add(new GpioConfig(8,40,"LCD_DATA7",0x8BC,"lcd_data7","gpmc_a7","pr1_edio_data_in7","eQEP2_strobe","pr1_edio_data_out7","pr1_pru1_pru_r30_7","pr1_pru1_pru_r31_7","*gpio2_13","hdmi"));
            outList.Add(new GpioConfig(8,41,"LCD_DATA4",0x8B0,"lcd_data4","gpmc_a4","pr1_mii0_txd1","eQEP2A_in","","pr1_pru1_pru_r30_4","pr1_pru1_pru_r31_4","*gpio2_10","hdmi"));
            outList.Add(new GpioConfig(8,42,"LCD_DATA5",0x8B4,"lcd_data5","gpmc_a5","pr1_mii0_txd0","eQEP2B_in","","pr1_pru1_pru_r30_5","pr1_pru1_pru_r31_5","*gpio2_11","hdmi"));
            outList.Add(new GpioConfig(8,43,"LCD_DATA2",0x8A8,"lcd_data2","gpmc_a2","pr1_mii0_txd3","ehrpwm2_tripzone_input","","pr1_pru1_pru_r30_2","pr1_pru1_pru_r31_2","*gpio2_8","hdmi"));
            outList.Add(new GpioConfig(8,44,"LCD_DATA3",0x8AC,"lcd_data3","gpmc_a3","pr1_mii0_txd2","ehrpwm0_synco","","pr1_pru1_pru_r30_3","pr1_pru1_pru_r31_3","*gpio2_9","hdmi"));
            outList.Add(new GpioConfig(8,45,"LCD_DATA0",0x8A0,"lcd_data0","gpmc_a0","pr1_mii_mt0_clk","ehrpwm2A","","pr1_pru1_pru_r30_0","pr1_pru1_pru_r31_0","*gpio2_6","hdmi"));
            outList.Add(new GpioConfig(8,46,"LCD_DATA1",0x8A4,"lcd_data1","gpmc_a1","pr1_mii0_txen","ehrpwm2B","","pr1_pru1_pru_r30_1","pr1_pru1_pru_r31_1","*gpio2_7","hdmi"));

            // add the Pins for P9 header
            outList.Add(new GpioConfig(9,11,"GPMC_WAIT0",0x870,"gpmc_wait0","gmii2_crs","gpmc_csn4","rmii2_crs_dv","mmc1_sdcd","pr1_mii1_col","uart4_rxd","*gpio0_30"));
            outList.Add(new GpioConfig(9,12,"GPMC_BEn1",0x878,"gpmc_be1n","gmii2_col","gpmc_csn6","mmc2_dat3","gpmc_dir","pr1_mii1_rxlink","mcasp0_aclkr","*gpio1_28"));
            outList.Add(new GpioConfig(9,13,"GPMC_WPn",0x874,"gpmc_wpn","gmii2_rxerr","gpmc_csn5","rmii2_rxerr","mmc2_sdcd","pr1_mii1_txen","uart4_txd","*gpio0_31"));
            outList.Add(new GpioConfig(9,14,"GPMC_A2",0x848,"gpmc_a2","gmii2_txd3","rgmii2_td3","mmc2_dat1","gpmc_a18","pr1_mii1_txd2","ehrpwm1A","*gpio1_18"));
            outList.Add(new GpioConfig(9,15,"GPMC_A0",0x840,"gpmc_a0","gmii2_txen","rgmii2_tctl","rmii2_txen","gpmc_a16","pr1_mii_mt1_clk","ehrpwm1_tripzone_input","*gpio1_16"));
            outList.Add(new GpioConfig(9,16,"GPMC_A3",0x84C,"gpmc_a3","gmii2_txd2","rgmii2_td2","mmc2_dat2","gpmc_a19","pr1_mii1_txd1","ehrpwm1B","*gpio1_19"));
            outList.Add(new GpioConfig(9,17,"SPI0_CS0",0x95C,"spi0_cs0","mmc2_sdwp","I2C1_SCL","ehrpwm0_synci","pr1_uart0_txd","pr1_edio_data_in1","pr1_edio_data_out1","*gpio0_5"));
            outList.Add(new GpioConfig(9,18,"SPI0_D1",0x958,"spi0_d1","mmc1_sdwp","I2C1_SDA","ehrpwm0_tripzone_input","pr1_uart0_rxd","pr1_edio_data_in0","pr1_edio_data_out0","*gpio0_4"));
            outList.Add(new GpioConfig(9,19,"UART1_RTSn",0x97C,"uart1_rtsn","timer5","dcan0_rx","I2C2_SCL","spi1_cs1","pr1_uart0_rts_n","pr1_edc_latch1_in","*gpio0_13"));
            outList.Add(new GpioConfig(9,20,"UART1_CTSn",0x978,"uart1_ctsn","timer6","dcan0_tx","I2C2_SDA","spi1_cs0","pr1_uart0_cts_n","pr1_edc_latch0_in","*gpio0_12"));
            outList.Add(new GpioConfig(9,21,"SPI0_D0",0x954,"spi0_d0","uart2_txd","I2C2_SCL","ehrpwm0B","pr1_uart0_rts_n","pr1_edio_latch_in","EMU3","*gpio0_3"));
            outList.Add(new GpioConfig(9,22,"SPI0_SCLK",0x950,"spi0_sclk","uart2_rxd","I2C2_SDA","ehrpwm0A","pr1_uart0_cts_n","pr1_edio_sof","EMU2","*gpio0_2"));
            outList.Add(new GpioConfig(9,23,"GPMC_A1",0x844,"gpmc_a1","gmii2_rxdv","rgmii2_rctl","mmc2_dat0","gpmc_a17","pr1_mii1_txd3","ehrpwm0_synco","*gpio1_17"));
            outList.Add(new GpioConfig(9,24,"UART1_TXD",0x984,"uart1_txd","mmc2_sdwp","dcan1_rx","I2C1_SCL","","pr1_uart0_txd","pr1_pru0_pru_r31_16","*gpio0_15"));
            outList.Add(new GpioConfig(9,25,"MCASP0_AHCLKX",0x9AC,"mcasp0_ahclkx","eQEP0_strobe","mcasp0_axr3","mcasp1_axr1","EMU4","pr1_pru0_pru_r30_7","pr1_pru0_pru_r31_7","*gpio3_21"));
            outList.Add(new GpioConfig(9,26,"UART1_RXD",0x980,"uart1_rxd","mmc1_sdwp","dcan1_tx","I2C1_SDA","","pr1_uart0_rxd","pr1_pru1_pru_r31_16","*gpio0_14"));
            outList.Add(new GpioConfig(9,27,"MCASP0_FSR",0x9A4,"mcasp0_fsr","eQEP0B_in","mcasp0_axr3","mcasp1_fsx","EMU2","pr1_pru0_pru_r30_5","pr1_pru0_pru_r31_5","*gpio3_19"));
            outList.Add(new GpioConfig(9,28,"MCASP0_AHCLKR",0x99C,"mcasp0_ahclkr","ehrpwm0_synci","mcasp0_axr2","spi1_cs0","eCAP2_in_PWM2_out","pr1_pru0_pru_r30_3","pr1_pru0_pru_r31_3","*gpio3_17"));
            outList.Add(new GpioConfig(9,29,"MCASP0_FSX",0x994,"mcasp0_fsx","ehrpwm0B","","spi1_d0","mmc1_sdcd","pr1_pru0_pru_r30_1","pr1_pru0_pru_r31_1","*gpio3_15"));
            outList.Add(new GpioConfig(9,30,"MCASP0_AXR0",0x998,"mcasp0_axr0","ehrpwm0_tripzone_input","","spi1_d1","mmc2_sdcd","pr1_pru0_pru_r30_2","pr1_pru0_pru_r31_2","*gpio3_16"));
            outList.Add(new GpioConfig(9,31,"MCASP0_ACLKX",0x990,"mcasp0_aclkx","ehrpwm0A","","spi1_sclk","mmc0_sdcd","pr1_pru0_pru_r30_0","pr1_pru0_pru_r31_0","*gpio3_14"));
            outList.Add(new GpioConfig(9,41,"XDMA_EVENT_INTR1",0x9B4,"xdma_event_intr1","","tclkin","clkout2","timer7","pr1_pru0_pru_r31_16","EMU3","*gpio0_20"));
            //?    outList.Add(new GpioConfig(9,41.1,"MCASP0_AXR1",0x9A8,"mcasp0_axr1","eQEP0_index","","mcasp1_axr0","EMU3","pr1_pru0_pru_r30_6","pr1_pru0_pru_r31_6","*gpio3_20"));
            outList.Add(new GpioConfig(9,42,"ECAP0_IN_PWM0_OUT",0x964,"eCAP0_in_PWM0_out","uart3_txd","spi1_cs1","pr1_ecap0_ecap_capin_apwm_o","spi1_sclk","mmc0_sdwp","xdma_event_intr2","*gpio0_7"));
            //? outList.Add(new GpioConfig(9,42.1,"MCASP0_ACLKR",0x9A0,"mcasp0_aclkr","eQEP0A_in","mcasp0_axr2","mcasp1_aclkx","mmc0_sdwp","pr1_pru0_pru_r30_4","pr1_pru0_pru_r31_4","*gpio3_18"));
            return outList;
*/
        }

        #region External Library Calls

        // these calls are in the libc.so.6 library. We can just say "libc" and mono
        // will figure out which libc.so is the latest version and use that.

        [DllImport("libc", EntryPoint = "ioctl")]
        static extern int ExternalIoCtl(int fd, int request, StringBuilder outStr);

        [DllImport("libc", EntryPoint = "open")]
        static extern int ExternalFileOpen(string path, int flags);

        [DllImport("libc", EntryPoint = "close")]
        static extern int ExternalFileClose(int fd);

        #endregion

    }
}

HTML Code Generated by CoDocker v00.90 Beta