gpiod - use labels in devicetree - linux-kernel

I want to use libgpiod to control a few GPIOs via userspace on a custom board. I have an i.MX6UL processor, which has hundreds of pins, I'll use only 8 of them (as GPIOs).
I read about the libgpiod as it is replacing the old sysfs API, and I'm happy that you can specify labels for each GPIO. The GPIO block of the processor looks like the following code block and has already the gpio-controller property set. (Taken from Linux kernel v4.14)
gpio2: gpio#20a0000 {
compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
reg = <0x020a0000 0x4000>;
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-ranges = <&iomuxc 0 49 16>, <&iomuxc 16 111 6>;
};
I want to use a single pin of this controller, so I added the following block:
&gpio2 {
resetl0 {
//gpio-hog;
output-high;
line-name = "COBO0_ResetL";
gpios = <15 1>;
};
};
Without the gpio-hog property, the gpioinfo tool is unable to show me the labels, same if I omit the output-high/low. With the property, the label is correctly displayed, but the gpio is marked as used, so I cannot control from userspace. (Device or resource busy)
So in short:
I need a way to set a label in device tree, which I'm able to read from userspace and to control the gpios. I already saw the gpio-line-names in the RPi devicetree, but I don't want to specify the whole bank as NC, when using only one. Is it possible with libgpiod? How?

I tested on Odroid-N2 kernel v5.4.
meson-g12b-odroid-n2.dts
&gpio {
gpio-line-names =
/* GPIOZ */
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
/* GPIOH */
"", "", "", "", "", "", "", "",
"",
/* BOOT */
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
/* GPIOC */
"", "", "", "", "", "", "", "",
/* GPIOA */
"44", "46", "45", "47",
"26", "", "", "",
"", "", "", "42",
"32", "7", "27", "28",
/* GPIOX */
"16", "18", "22", "11",
"13", "33", "35", "15",
"19", "21", "24", "23",
"8", "0", "29", "31",
"12", "3", "5", "36";
usb-hub {
gpio-hog;
gpios = <GPIOH_4 GPIO_ACTIVE_HIGH>;
output-high;
line-name = "usb-hub-reset";
};
};
Output of gpioinfo
gpiochip0 - 85 lines:
...
line 20: unnamed "usb-hub-reset" input active-high [used]
...
line 49: "44" unused input active-high
line 50: "46" unused input active-high
line 51: "45" unused input active-high
line 52: "47" unused input active-high
line 53: "26" unused input active-high
...
line 60: "42" unused input active-high
line 61: "32" unused input active-high
line 62: "7" unused input active-high
line 63: "27" unused input active-high
line 64: "28" unused input active-high
line 65: "16" unused input active-high
line 66: "18" unused input active-high
line 67: "22" unused input active-high
line 68: "11" unused input active-high
line 69: "13" unused input active-high
line 70: "33" unused input active-high
line 71: "35" unused input active-high
line 72: "15" unused input active-high
line 73: "19" unused input active-high
line 74: "21" unused input active-high
line 75: "24" unused input active-high
line 76: "23" unused input active-high
line 77: "8" unused input active-high
line 78: "0" unused input active-high
line 79: "29" unused input active-high
line 80: "31" unused input active-high
line 81: "12" unused input active-high
line 82: "3" unused input active-high
line 83: "5" unused input active-high
line 84: "36" unused input active-high
...
gpioinfo displayed 'gpio-line-names' as a name and 'line-name' as a consumer.

Related

how to get Go Delve debugger (dlv) 'display' command to show all values of a slice or map

I'm trying to use the Delve (dlv) "display" command to show the values of a slice and a map. The "print" command shows the full value but "display" only ever shows "[...]"
contrast the display and print output below
(dlv) display
0: gns = []string len: 2, cap: 2, [...]
1: chGnMap = map[string]int [...]
(dlv) p gns
[]string len: 2, cap: 2, ["ecam","site"]
(dlv) p chGnMap
map[string]int [
"ecam": 2,
"site": 2,
]
(dlv) config -list
aliases map[]
substitute-path []
max-string-len 1024
max-array-values 1024
max-variable-recurse 10
disassemble-flavor <not defined>
show-location-expr false
source-list-line-color <nil>
source-list-arrow-color ""
source-list-keyword-color ""
source-list-string-color ""
source-list-number-color ""
source-list-comment-color ""
source-list-line-count <not defined>
debug-info-directories [/usr/lib/debug/.build-id]
(dlv) exit
# dlv version
Delve Debugger
Version: 1.7.2
This doesn't entirely answer your question, but:
When you are adding your display variables display -a ..., you can reference a key in the dictionary.
See steps below:
Add map w/ key supplied using display -a
Show that the key currently doesn't exist
The key is automatically added when the program advances
Note: I needed to append [0] to the display line because
handlerHeader["Content-Type"] returns a string slice.
(dlv) args
handler = (*main.ProduceHandler)(0x14000112d10)
wri = net/http.ResponseWriter(*net/http.response) 0x14000193708
req = ("*net/http.Request")(0x14000182000)
(dlv) display -a wri.w.wr.res.handlerHeader["Content-Type"][0]
0: wri.w.wr.res.handlerHeader["Content-Type"][0] = error key not found
(dlv) print %T wri.w.wr.res.handlerHeader
net/http.Header []
(dlv) n
> main.(*ProduceHandler).ServeHTTP() ./api.go:144 (PC: 0x100984480)
139: switch req.Method {
140: case http.MethodGet:
141: if len(req.URL.Query()["code"]) == 0 {
142: log.Println("Sending entire produce database")
143: wri.Header().Add("Content-Type", "application/json")
=> 144: wri.WriteHeader(http.StatusOK)
145: json.NewEncoder(wri).Encode(handler.DB)
146: return
147: }
148:
149: c := req.URL.Query()["code"][0]
0: wri.w.wr.res.handlerHeader["Content-Type"][0] = "application/json"

How can I get the Flag chosen by the user in my CLI

I have specified some flags like you can see below:
deleteCmd.Flags().StringVarP(&option, "wallet", "w", "", "Specify the wallet to be deleted")
deleteCmd.Flags().StringVarP(&option, "holding", "o", "", "Specify the holding to be deleted")
deleteCmd.Flags().StringVarP(&option, "ticker", "t", "", "Specify the ticker to be deleted")
deleteCmd.Flags().StringVarP(&option, "tag", "g", "", "Specify the tag to be deleted")
Once I'll use those to know what to delete when consuming my API, Is there any way to get the flag value that my user choose?
This solution has very bad design... You do not know order of eveluating those flags.
The issue
I am assuming you are using cobra. So when you read documentation you will not find any part of how your flags are evaluated. So sometimes it is called undefined behavior and it may work but if the future it may be changed
Let's analyze your example:
deleteCmd.Flags().StringVarP(&option, "wallet", "w", "", "Specify the wallet to be deleted")
deleteCmd.Flags().StringVarP(&option, "holding", "o", "", "Specify the holding to be deleted")
deleteCmd.Flags().StringVarP(&option, "ticker", "t", "", "Specify the ticker to be deleted")
deleteCmd.Flags().StringVarP(&option, "tag", "g", "", "Specify the tag to be deleted")
You have the following flags: wallet, holding, ticker, tag. We can assume order is how you put it in your code. Let's say potential behavior:
User put the ticker flag. Default value for all flags is empty. So the option variable has an empty value, which comes from the tag flag.
The solution
You should use separated variable for each flag. And you should implement your logic to cover the part to determine which flag has been put.
deleteCmd.Flags().StringVarP(&wallet, "wallet", "w", "", "Specify the wallet to be deleted")
deleteCmd.Flags().StringVarP(&holding, "holding", "o", "", "Specify the holding to be deleted")
deleteCmd.Flags().StringVarP(&ticker, "ticker", "t", "", "Specify the ticker to be deleted")
deleteCmd.Flags().StringVarP(&tag, "tag", "g", "", "Specify the tag to be deleted")
if wallet != "" {
option = wallet
selected = "wallet"
} else if holding != "" {
option = holding
selected = "holding"
} else ...
...
...

Sonar scanner error: Unable to parse file

We have implemented ESlint Plugin in Sonarqube 5.6.6 for performing Sonar anlysis of a Javascript project.
I am executing the following tasks:
Checking out the code from repository
Running sonar-scanner on the checked out code.
Although the task is getting executed successfully, but I am getting an error while executing the task. the logs for the error part is as follows:
19:57:54.069 ERROR: Unable to parse file: /ebs/deployment/codebases/test-design/sonar/lib/atomic/List/LI/index.js
19:57:54.071 ERROR: Parse error at line 14 column 40:
4:
5: import React from 'react';
6: import classnames from 'classnames';
7: import PropTypes from 'prop-types';
8: import styles from './LI.css';
9:
10:
11: // eslint-disable-next-line
12: console.log(styles.length);
13:
14: const LI = ({ ...props, children, data = {}, titleKey = '', className = {}, styleNames, style, onClick, onMouseOver, onMouseOut }) => (
^
15: <li
16: {...props}
17: className={classnames(className)}
18: style={style}
19: data={data}
20: styleName={`li ${styleNames}`}
21: >
22: <button
23: styleName="buttonsStyles"
24: onClick={event => onClick(event, data)}
19:57:54.574 ERROR: Unable to parse file: /ebs/deployment/codebases/test-design/sonar/lib/atomic/Tabs/index.js
19:57:54.576 ERROR: Parse error at line 46 column 22:
36: className={className}
37: onMouseOver={onMouseOver}
38: onMouseOut={onMouseOut}
39: onClick={onClick}
40: />)
41: ))}
42: </UL>);
43:
44: const BorderedTab = ({
45: ...props,
46: liActiveStyleNames = '',
^
47: liStyleNames = '',
48: ulStyleNames = '',
49: }) => (<TabComponent
50: {...props}
51:
52: liStyleNames={`borderedTab ${liStyleNames || ''}`}
53: liActiveStyleNames={`borderedTabAcive ${liActiveStyleNames || ''}`}
54: ulStyleNames={`borderedTab ${ulStyleNames || ''}`}
55: />);
56:
Although the job ran successfully, but I am not sure whether the analysis is correct or not.
The sonar-scanner command is as follows:
sonar-scanner -Dsonar.sources=. -Dsonar.projectVersion=v1 -Dsonar.projectKey=test-design -Dsonar.projectName=test-DesigneSystem -Dsonar.host.url=http://localhost:9000 '-Dsonar.exclusions=**/font/**' -X
The profiles which we are using: csslint, eslint
Can anybody tell me what may be the issue.

Bad instruction error Swift 3 and XCode 8

I've been learning Swift 3 syntax lately and I thought that a good first project would be a Vigenère Cipher. So I've begun to create a script for it in Playground.
The issue is that I keep getting an error when I call the method and I know what the mistake is, it has to do with how I am calling my Dictionary value and the fact that I am unwrapping it, But I don't know what else to do about it. Any ideas?
import Foundation
let alphabet: [String: Int] = ["a": 0, "b": 1, "c": 2, "d": 3, "e": 4, "f": 5, "g": 6, "h": 7, "i": 8,
"j": 9, "k": 10, "l": 11, "m": 12, "n": 13, "o": 14, "p": 15, "q": 16,
"r": 17, "s": 18,"t": 19, "u": 20, "v": 21, "w": 22, "x": 23, "y": 24, "z": 25]
let alphabet2: [Int: String] = [0: "a", 1: "b", 2: "c", 3: "d", 4: "e", 5: "f", 6: "g", 7: "h", 8: "i",
9: "j", 10: "k", 11: "l", 12: "m", 13: "n", 14: "o", 15: "p", 16: "q",
17: "r", 18: "s", 19: "t", 20: "u", 21: "v", 22: "w", 23: "x", 24: "y", 25: "z"]
var mess = "I once saw a big mosquito"
var key = "pass"
func cipher(message: String, key: String) -> String{
var code: [Int] = [] // will hold the encripted code
// removes whietspace from message and key
let trimmedMessage = message.trimmingCharacters(in: NSCharacterSet.whitespaces)
let trimmedKey = key.trimmingCharacters(in: NSCharacterSet.whitespaces)
// Sets the key the same size as the message
let paddedTrimmedKey = trimmedKey.padding(toLength: message.characters.count, withPad: trimmedKey, startingAt: 0)
// separates the message and key into individual characters
let charTrimmedMessage = Array(trimmedMessage.characters)
let charPaddedTrimmedKey = Array(paddedTrimmedKey.characters)
// Compare the values in the key to the message and scrambles the message.
var i = 0
for chr in charTrimmedMessage{
code.append((alphabet[String(chr)]! + alphabet[String(charPaddedTrimmedKey[i])]!) % 26) // <- I think the error comes from this line. Maybe the exclamation marks?
i += 1
}
var cyphr: String = "" // this will hold the return String
// I think I could have used some sort of "join" function here.
for number in code{
cyphr = cyphr + alphabet2[number + 1]!
}
return cyphr
}
cipher(message: mess, key: key) // <--- this returns an error, no clue why. The code works and compiles great.
I get this error:
If you could let me know any pointer on how to improve my code to avoid things like this even better.
Your alphabet dictionary does not have lookup values for the letters "I", " " which are contained in your plain text. The cipher function fails because of this (since it is force unwrapping an optional which is nil)
If you initialize the mess variable, you will get the cipher to work
var mess = "ioncesawabigmosquito"
cipher(...) -> "ypgvuttpqcbzcpljkjmh"
Either
update the alphabet lookup dictionary. E.g. add ' ' as a valid input, update alphabet2 to provide reverse lookup, and change the mod factor from 26 to 27 (to account for new ' ' character)
OR
validate your input beforehand. (trim spaces, replace spaces, convert uppercase to lowercase / strip characters not in valid range)
To trim your input to only include valid letters in the alphabet, you could try:
let validSet = CharacterSet.init(charactersIn: alphabet.keys.joined())
var messTrimmed = mess.trimmingCharacters(in: validSet.inverted)
Note that doing this mean losing information from the original message
Another bug:
The line cyphr = cyphr + alphabet2[number+1]! should be cyphr = cyphr + alphabet2[number]!.
It's not correct to add 1 to number since the values in the code array are computed mod 26, and the max key value in alphabet is 25. It will cause an exception when force unwrapping to a non-existent key.
E.g. try cipher(message: "ypgvuttpqcbzcpljkjmh", key: "pass") to make it fail.
Footnote
As a complete aside, here's a variant of the cipher function (I have not sanitized the inputs; just showing how the code could be written in a functional way)
func cipher2(message: String, key: String) -> String {
return
message
.characters
.enumerated()
.map { ($0, String($1)) }
.map {
(
alphabet[$1]!
+ alphabet[String(key[key.index(key.startIndex, offsetBy: ($0 % key.characters.count))])]!
) % 26
}
.map { alphabet2[$0]! }
.joined()
}

Go detects concurrent read and write on map despite locks

I'm writing a simple caching mechanism which has an Add an Evict and a Search method. The Search is currently not implemented yet, so there's no need to worry about that.
There's a relatively large number of goroutines that call Add to add data and there's only one which runs in an evict loop to evict data. As soon as I put some serious traffic on it Go throws up saying there's a concurrent read and write access on the map metricCache, but I can't see how that can happen because there are locks around it. I'm using Go 1.7.
File mdata/cache.go:
57: func NewCCache() *CCache {
58: cc := &CCache{
59: lock: sync.RWMutex{},
60: metricCache: make(map[string]*CCacheMetric),
61: accnt: accnt.NewFlatAccnt(maxSize),
62: }
63: go cc.evictLoop()
64: return cc
65: }
66:
67: func (c *CCache) evictLoop() {
68: evictQ := c.accnt.GetEvictQ()
69: for target := range evictQ {
70: c.evict(target)
71: }
72: }
73:
74: func (c *CCache) Add(metric string, prev uint32, itergen chunk.IterGen) {
75: c.lock.Lock()
76:
77: if ccm, ok := c.metricCache[metric]; !ok {
78: var ccm *CCacheMetric
79: ccm = NewCCacheMetric()
80: ccm.Init(prev, itergen)
81: c.metricCache[metric] = ccm
82: } else {
83: ccm.Add(prev, itergen)
84: }
85: c.lock.Unlock()
86:
87: c.accnt.AddChunk(metric, itergen.Ts(), itergen.Size())
88: }
89:
90: func (c *CCache) evict(target *accnt.EvictTarget) {
91: c.lock.Lock()
92:
93: if _, ok := c.metricCache[target.Metric]; ok {
94: log.Debug("cache: evicting chunk %d on metric %s\n", target.Ts, target.Metric)
95: length := c.metricCache[target.Metric].Del(target.Ts)
96: if length == 0 {
97: delete(c.metricCache, target.Metric)
98: }
99: }
100:
101: c.lock.Unlock()
102: }
That's the error message:
metrictank_1 | fatal error: concurrent map read and map write
metrictank_1 |
metrictank_1 | goroutine 3159 [running]:
metrictank_1 | runtime.throw(0xaade7e, 0x21)
metrictank_1 | /usr/local/go/src/runtime/panic.go:566 +0x95 fp=0xc4216a7eb8 sp=0xc4216a7e98
metrictank_1 | runtime.mapaccess2_faststr(0x9e22c0, 0xc42031e600, 0xc4210c2b10, 0x22, 0x28, 0xa585d5496)
metrictank_1 | /usr/local/go/src/runtime/hashmap_fast.go:306 +0x52b fp=0xc4216a7f18 sp=0xc4216a7eb8
metrictank_1 | github.com/raintank/metrictank/mdata/cache.(*CCache).Add(0xc4202fa070, 0xc4210c2b10, 0x22, 0x0, 0xc421875f82, 0x25, 0x25, 0xa585d5496)
metrictank_1 | /home/mst/go/src/github.com/raintank/metrictank/mdata/cache/cache.go:77 +0x63 fp=0xc4216a7f80 sp=0xc4216a7f18
metrictank_1 | runtime.goexit()
metrictank_1 | /usr/local/go/src/runtime/asm_amd64.s:2086 +0x1 fp=0xc4216a7f88 sp=0xc4216a7f80
metrictank_1 | created by github.com/raintank/metrictank/api.(*Server).getSeries
metrictank_1 | /home/mst/go/src/github.com/raintank/metrictank/api/dataprocessor.go:442 +0x122b
UPDATE: I recompiled with -race and now I'm getting a different error. This looks as if the RWMutex were completely ineffective because according to the backtraces the problem must be in the combination of the evict and Add methods.
==================
WARNING: DATA RACE
Read at 0x00c4201c81e0 by goroutine 215:
runtime.mapaccess2_faststr()
/usr/local/go/src/runtime/hashmap_fast.go:297 +0x0
github.com/raintank/metrictank/mdata/cache.(*CCache).Add()
/home/mst/go/src/github.com/raintank/metrictank/mdata/cache/cache.go:77 +0xaa
Previous write at 0x00c4201c81e0 by goroutine 155:
runtime.mapdelete()
/usr/local/go/src/runtime/hashmap.go:558 +0x0
github.com/raintank/metrictank/mdata/cache.(*CCache).evict()
/home/mst/go/src/github.com/raintank/metrictank/mdata/cache/cache.go:97 +0x30e
github.com/raintank/metrictank/mdata/cache.(*CCache).evictLoop()
/home/mst/go/src/github.com/raintank/metrictank/mdata/cache/cache.go:70 +0xb3
Goroutine 215 (running) created at:
github.com/raintank/metrictank/api.(*Server).getSeries()
/home/mst/go/src/github.com/raintank/metrictank/api/dataprocessor.go:442 +0x17c9
github.com/raintank/metrictank/api.(*Server).getTarget()
/home/mst/go/src/github.com/raintank/metrictank/api/dataprocessor.go:331 +0x9c3
github.com/raintank/metrictank/api.(*Server).getTargetsLocal.func1()
/home/mst/go/src/github.com/raintank/metrictank/api/dataprocessor.go:284 +0xa9
Goroutine 155 (running) created at:
github.com/raintank/metrictank/mdata/cache.NewCCache()
/home/mst/go/src/github.com/raintank/metrictank/mdata/cache/cache.go:63 +0x12f
main.main()
/home/mst/go/src/github.com/raintank/metrictank/metrictank.go:388 +0x246c
==================
A colleague of mine has found the answer:
After calling NewCCache() I copied the returned variable by value (including the lock) and then called Add() on the copy, at the same time the evictLoop() go routine was still referring to the old copy. So they were operating on different copies of the lock :)

Resources