PCEngines – APU Board and nct5104d gpio driver

The board 🙂

Today I will explain you how I managed to write my own custom driver for nct5104d under Centos running on PCEngines APU board . But before we go any further wanted to share my “big wow” to the makers of the board. For anyone doing home automation , tinkering around or being just interested in engineering it is something I can completely recommend. It features amongst many cool perks things like 3 Gig ethernet ports , 16(18) GPIO ports , I2C , 2xRS232 ( one with RX,TX only ). For me its 5/5 start rating 🙂


In a place far far away…

… I have started this post some time ago since I thought it would be a great idea to have opportunity of sharing my experience as I  go through the whole learning of how to write a Linux driver for nct5104d  ( sitting on APU board )

Before I decided to anything crazy like that I would like to let you know that there is already a driver for the device and you can find it https://github.com/tasanakorn/linux-gpio-nct5104d . What made me thinking of writing my version was the way I would need to interoperate with the GPIOs by making some funky commands like :

echo 1 > /sys/class/gpio/gpio0/value

At that moment I knew I can make it easier for my automation purposes 🙂


Writing own driver …  where to start ?

So this is good question to ask yourself here. It took me many hours of reading articles/forums but also talking with people that have been doing such things before. From a high level perspective its simple – read basics and then start small with hello world. Once you start understanding it you will have more results.

I could recommend you take a look at the following resources ( which I have found very useful for getting my head around 🙂  )


Step by step ?


In most of my articles we would probably dive into technical details of the challenge. But in this instance I will point you to my github repository and ask to take a look. There has been a big amount of work that I have put into this and if you will have specific questions I will be here to try and answer them!


As just as interesting part – thats how my work looked like though the last 2 weeks ( from start to finish 🙂 )

Where is the code ?

The complete repository is available in my github repo https://github.com/RafPe/gpio-driver-nct5104d


So how does it work ?

Now we are talking 🙂 So using the driver is really nice. Once you go through the steps of compiling it and installing in your system you then have access to device via ioctl.

I have exposed methods for interacting with registries and with pins. However what is important here – the device automatically uses Logical device 7 which is GPIO. If you would have other needs we would most likely need to compile some logic around it.

Since not everyone is guru in creating binaries 🙂 I have created 2 apps which are respectively for management of pins or registries


Managing pins

With simple commands you can manage pins instantly

nct5104dpin [ --get|--set ] [--pin ] --val < 0|1 > --dir <out|in>

Get a pin value: nct5104dpin --pin 7 
Get a pin value: nct5104dpin --get --pin 14
Set a pin value: nct5104dpin --set --pin 14 --val 1
Set a pin direction: nct5104dpin --set --pin 14 --dir out

Cool thing is that I have made it in such a way that parsing data with i.e. JQ is just straightforward.

[email protected] > nct5104dpin --pin 1 | jq
    "pin": 1,
    "value": 0

Managing registries

Same apply for managing registers. I have been aiming to keep it simple and specific.

ct5104dreg [ --get|--set ] [--reg ] <HEX> --val <DECIMAL> 

Get a reg value: nct5104dreg --reg 0x07 
Get a reg value: nct5104dreg --get --reg 0x07
Set a reg value: nct5104dreg --set --reg 0xE0 --val 252

Here I also made sure output can easily be parsed

[email protected] > nct5104dreg --reg 0xE1 | jq
    "registry": "0xe1",
    "value": 248


Adventure begins here

I hope by sharing this I will enable you or maybe someone else to do things that you have not been doing before 🙂 or at least get you interested



PowerShell – Creating PSObject from template

When working with PowerShell I have came across really cool way to work with PSObjects. It’s being simple as creating one of the underlying object methods. But first things first – let’s create one template object

$AccessRules = New-Object PsObject
$AccessRules.PsObject.TypeNames.Insert(0, "FileSystemAccessRules")
$AccessRules | Add-Member -MemberType NoteProperty -Name subFolder -Value ''
$AccessRules | Add-Member -MemberType NoteProperty -Name identity -Value ''
$AccessRules | Add-Member -MemberType NoteProperty -Name rights -Value ''
$AccessRules | Add-Member -MemberType NoteProperty -Name InheritanceFlags -Value ''
$AccessRules | Add-Member -MemberType NoteProperty -Name accessControlType -Value ''
$AccessRules | Add-Member -MemberType NoteProperty -Name preserveInheritance -Value ''
$AccessRules | Add-Member -MemberType NoteProperty -Name isInherited -Value ''
$AccessRules | Add-Member -MemberType NoteProperty -Name owner -Value ''
$AccessRules | Add-Member -MemberType NoteProperty -Name PropagationFlags -Value ''


Thats really easy – now its time to simply us it as base for other created objects

$FS_TMP_AR_1 = $AccessRules.psobject.Copy()

$FS_TMP_AR_1.accessControlType = 'Állow'
$FS_TMP_AR_1.identity          = 'BUILTIN\Administrators'
$FS_TMP_AR_1.InheritanceFlags  = "ContainerInherit, ObjectInherit"
$FS_TMP_AR_1.isInherited       = 1
$FS_TMP_AR_1.owner             = "BUILTIN\Administrators"
$FS_TMP_AR_1.preserveInheritance = 1
$FS_TMP_AR_1.rights              = 'FullControl'
$FS_TMP_AR_1.subFolder           = ''
$FS_TMP_AR_1.PropagationFlags ="None"


And thats it – voilla 😉 the whole magic is just hidden under this line



Hope this helps – happy coding!


HAproxy – backend and domain management using map

This is quick write up how to use single line for easy backend mapping within HAproxy. This has been showed to me by my buddy while challenging current configuration which started to grow.

The first thing you will need to have is to create a map file. Its structure its simple – first column is what comes is , second is what comes out. So for our domain mapping we can have file with domain name and respective backend i.e.

domain.com backend_com
www.domain.com backend.com

Next is just configuration line on your front end associating domains with backends based on the host header

use_backend %[req.hdr(host),lower,map_dom(/etc/haproxy/<PATH-TO-MAP-FILE>,<DEFAULT-BACKEND>)]


And that is it 🙂 you have now got your self really dynamic configuration