Accessing GPIO on OrangePI PC Plus ( H3 ) on Armbian 3.4.113 and newer - gpio

how to access GPIO on Armbian 3.4.113 on OrangePi PC plus ( SoC H3 ) now that the old method using gpio-sunxi and editing the .fex-file is obsolete ( want to share this ... )

The general proceeding is described in https://linux-sunxi.org/GPIO
The GPIO pins are accessed via the sysfs file system. For enabling a specific pin it has to be exported into /sys/class/gpio/export
for pin PA1 the command would be echo 1 > sys/class/gpio/export. The pin number is calculated by the following formula :
(position of letter in alphabet - 1) * 32 + pin number
PA1 has pin number ('A' is the 1st letter ) 1, PB2 has pin number 34 ('B' is 2nd letter ), PG7 has pin number 199( 'G' is 7th letter (7-1)*32+7=199 )
the positions on the physical header are different again, cf. the graphic below
so for enabling PG7 that is pin 40 on the physical header can be used
echo 199 > sys/class/gpio/export
source of image : https://orange314.com/Hardware
normally the echo command like echo "199" sys/class/gpio/export gives a Permission denied error
an easy solution are the following:
To do a one-off manipulation of a GPIO pin, you have to start a
separate shell as a superuser first, then use echo. For instance to
turn pin A10 on:
$ sudo sh
# echo 10 > /sys/class/gpio/export
# echo out > /sys/class/gpio/gpio10/direction
# echo 1 > /sys/class/gpio/gpio10/value
Or you can use tee to avoid creating a subshell:
$ echo 10 | sudo tee /sys/class/gpio/export
$ echo out | sudo tee /sys/class/gpio/gpio10/direction
$ echo 1 | sudo tee /sys/class/gpio/gpio10/value
source: https://forum.armbian.com/index.php?/topic/4052-problem-using-gpio-pins-on-legacy-kernel/
An alternative would be to create a new group and change the group of the /sys/class/gpio directory to this new group :
you can create a group called gpio, add the user to it, export the gpio
etc as follows:
sudo groupadd gpio
sudo usermod -aG gpio <myusername>
su <myusername>
sudo chgrp gpio /sys/class/gpio/export
sudo chgrp gpio /sys/class/gpio/unexport
sudo chmod 775 /sys/class/gpio/export
sudo chmod 775 /sys/class/gpio/unexport
This gives your user the ability to export and un-export.
Once you export the pins you can chgrp and chmod them as well (don't
forget their contents) and use them as usual.
echo "18" > /sys/class/gpio/export
chgrp -HR /sys/class/gpio/gpio18
chmod -R 775 /sys/class/gpio/gpio18
Now your user has access to the first GPIO pin 18.
source : https://www.raspberrypi.org/forums/viewtopic.php?t=5185
when executing the echo with permissions a new directory appears in /sys/class/gpio i.e. for PA2 ( which is pin number 2 and number 22 on the physical header ) it is /sys/class/gpio/gpio2
to configure pin number 2 you have to write specific values to the files in /sys/class/gpio/gpio2
for i.e. setting pin 2 to output and 'high' write
echo "out" > /sys/class/gpio/gpio2/direction
echo "1" > /sys/class/gpio/gpio2/value
when shutting down GPIO the pins should be unexported with i.e.
echo 2 > /sys/class/gpio/unexport for pin 2 ( PA2, number 22 on the physical header )
An alternative for accessing GPIO is using python, however for the H3 based boards the WiringOP is not available yet

Related

Cannot get a RPi Zero to emulate _both_ a USB Keyboard _and_ Mouse

I am trying to get my RPi Zero W to emulate a keyboard and mouse. I can get it to emulate a keyboard or a mouse successfully, but not both at the same time.
I followed the instructions at iStickToIt and Key Mime Pi to successfully emulate a keyboard. Alternatively I followed the instructions here to successfully emulate a mouse. Both work fine on their own. However I don't know how to emulate both mouse and keyboard at once.
I thought that perhaps I just needed to combine the information and define 2 functions for the 1 USB gadget, creating /dev/hidg0 and /dev/hidg1, but only the 1st one works. Below is my combined code - you can see that the Report Length and Report Descriptor is different for keyboard and mouse. But only /dev/hidg0 works (keyboard).
Can you suggest where I am going wrong?
#!/usr/bin/env bash
# Adapted from https://github.com/girst/hardpass-sendHID/blob/master/README.md
# Exit on first error.
set -e
# Treat undefined environment variables as errors.
set -u
modprobe libcomposite
cd /sys/kernel/config/usb_gadget/
mkdir -p g1
cd g1
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
STRINGS_DIR="strings/0x409"
mkdir -p "$STRINGS_DIR"
echo "82bc64754ca7384d7c90" > "${STRINGS_DIR}/serialnumber"
echo "Anykey" > "${STRINGS_DIR}/manufacturer"
echo "Generic USB Keyboard" > "${STRINGS_DIR}/product"
# -- Function 1: Keyboard -----------------------------------------------
FUNCTIONS_DIR="functions/hid.usb0"
mkdir -p "$FUNCTIONS_DIR"
echo 1 > "${FUNCTIONS_DIR}/protocol"
echo 0 > "${FUNCTIONS_DIR}/subclass" # No subclass
echo 8 > "${FUNCTIONS_DIR}/report_length"
# Write the report descriptor
# Source: https://www.kernel.org/doc/html/latest/usb/gadget_hid.html
echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > "${FUNCTIONS_DIR}/report_desc"
CONFIG_INDEX=1
CONFIGS_DIR="configs/c.${CONFIG_INDEX}"
mkdir -p "$CONFIGS_DIR"
echo 250 > "${CONFIGS_DIR}/MaxPower"
CONFIGS_STRINGS_DIR="${CONFIGS_DIR}/strings/0x409"
mkdir -p "$CONFIGS_STRINGS_DIR"
echo "Config ${CONFIG_INDEX}: ECM network" > "${CONFIGS_STRINGS_DIR}/configuration"
ln -s "$FUNCTIONS_DIR" "${CONFIGS_DIR}/"
# -- Function 2: Mouse --------------------------------------------------
FUNCTIONS_DIR="functions/hid.usb1"
mkdir -p "$FUNCTIONS_DIR"
echo 1 > "${FUNCTIONS_DIR}/protocol"
echo 0 > "${FUNCTIONS_DIR}/subclass" # No subclass
echo 3 > "${FUNCTIONS_DIR}/report_length"
# Write the report descriptor
# Source: https://www.kernel.org/doc/html/latest/usb/gadget_hid.html
echo -ne \\x05\\x01\\x09\\x02\\xa1\\x01\\x09\\x01\\xa1\\x00\\x05\\x09\\x19\\x01\\x29\\x03\\x15\\x00\\x25\\x01\\x95\\x03\\x75\\x01\\x81\\x02\\x95\\x01\\x75\\x05\\x81\\x03\\x05\\x01\\x09\\x30\\x09\\x31\\x15\\x81\\x25\\x7f\\x75\\x08\\x95\\x02\\x81\\x06\\xc0\\xc0 > "${FUNCTIONS_DIR}/report_desc"
CONFIG_INDEX=2
CONFIGS_DIR="configs/c.${CONFIG_INDEX}"
mkdir -p "$CONFIGS_DIR"
echo 250 > "${CONFIGS_DIR}/MaxPower"
CONFIGS_STRINGS_DIR="${CONFIGS_DIR}/strings/0x409"
mkdir -p "$CONFIGS_STRINGS_DIR"
echo "Config ${CONFIG_INDEX}: ECM network" > "${CONFIGS_STRINGS_DIR}/configuration"
ln -s "$FUNCTIONS_DIR" "${CONFIGS_DIR}/"
ls /sys/class/udc > UDC
chmod 777 /dev/hidg0
chmod 777 /dev/hidg1
I have found the answer to my own question. The mistake is in the 2 lines which say:
ln -s "$FUNCTIONS_DIR" "${CONFIGS_DIR}/"
Having set up 2 functions directories, they should both be linked into the same config directory and not 2 different config directories as I have done. So in my example one function directory was linked into "configs/c.1" and the other was linked into "configs/c.2", whereas they should both have been linked into "configs/c.1".
You can see a working report descriptor for both mouse and keyboard in the code for TinyPilot here. Note that this uses a slightly different mouse message format from my example above.
When you have set it up correctly use /dev/hidg0 for the keyboard and /dev/hidg1 for the mouse.
(With thanks to Michael Lynch, whose open-source RPi KVM project TinyPilot can be referred to here and here.)

Ubuntu sound/network/USB trouble after suspend , how to restart

I had a lengthy problem with Ubuntu 14.04 with Lenovo S20-30: after resuming suspended session some things break:
USB stops recognizing devices
due to this the webcam and bluetooth stop working
NetworkManager goes to sleep and no internet connections are made
Sound stops or hangs up in false "Headphones" mode,
or "Dummy" output is shown in Settings->Sound
This is a summary of many different answers (from the stack and others) on this topic which worked consistently for me:
to restart USB run in terminal as root e.g. in a scipt:
#!/bin/bash
for I in $(ls /sys/bus/pci/drivers/xhci_hcd/|grep : ) ; do
echo $I
sudo echo $I > /sys/bus/pci/drivers/xhci_hcd/unbind
sudo echo $I > /sys/bus/pci/drivers/xhci_hcd/bind
done
to wake up (resume) NetworkManager as normal user
#!/bin/bash
nmcli nm sleep false
to restart the sound as root
#!/bin/bash
pulseaudio -k ; sudo modprobe -fr snd_hda_intel; sudo modprobe snd-hda-intel
this solves the common message which came up upon restart:
modprobe: FATAL: Module snd_hda_intel is in use.
Adapting the answer by IljaBek into an automate one. Place the following script in a new file called:
/etc/pm/sleep.d/20_usb_unbind_bind
#!/bin/sh
# Action script to ubind then bind USB devices after sleep
#
case "${1}" in
hibernate)
# nothing
;;
resume|thaw)
for I in $(ls /sys/bus/pci/drivers/xhci_hcd/|grep : ) ; do
echo $I > /sys/bus/pci/drivers/xhci_hcd/unbind
echo $I > /sys/bus/pci/drivers/xhci_hcd/bind
done
;;
esac
Make the file executable with sudo chmod 755 /etc/pm/sleep.d/20_usb_unbind_bind

Unable to write on /dev/* files

I'm writing a basic char device driver for Linux kernel.
For this, the code flow I have considered is as follows:
alloc_chrdev_region() -> to use dynamic allocation of major number
class_create() -> to create device class in sysfs
device_creat() -> to create device under /dev/
cdv_init() -> to initialize char device structure
cdev_add() -> to add my device structure in kernel
I have added read, write, open, release methods in code.
When I try to read device file under /dev/ my read method is called.
But when I try to write on /dev/ file using echo it gives error
"bash: /dev/scull: Permission denied"
I have checked permissions of file using ls -l, and I have permissions to read or write on this file.
This problem occurs for every device driver module I have written. It works well in on another machine.
I'm working on ubuntu 15.10, custom compiled kernel 4.3.0
the result of ls -l /dev/scull:
crw------- 1 root root 247, 0 Dec 30 18:06 /dev/scull
the exact command I used to open the file
$ sudo echo 54 > /dev/scull
the source code for the open implementation
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){
pr_alert("Device Written\n");
return 0;
}
Behavior I'm seeking here is, I should be able to see 'Device Written' in dmesg ouput?
I assume that you are normally not root on your bash shell. Then this command line
sudo echo 54 > /dev/scull
does not what you think. The command is executed in two steps:
The bash setups the output redirection, i.e., it tries to open /dev/scull with the current user privileges.
The command sudo echo 54 is executed whereas stdout is connected to the file.
As you have no write-permissions as non-root user, the first step fails and the bash reports
"bash: /dev/scull: Permission denied"
You must already be root to setup the output redirection. Thus execute
sudo -i
which gives you an interactive shell with root privileges. The you can execute
echo 54 > /dev/scull
within that root shell.
I know the thread is too old to answer but just in case if someone wants to know alternative method without switching to root user, here is the solution:
sudo bash -c 'echo "54" > /dev/my_dev'
I wanted to note that on your system only root (file owner) has read / write permissions. Your (normal) user account has not! So another (fast) solution would be to give all users read / write permissions.
Probably this is not the safest solution! Only do this in your test environment!
sudo chmod a+rw /dev/scull
But now you test your module with your user account (without sudo)
echo "hello, world!" > /dev/scull
cat < /dev/scull
You can do so while going root with the command
sudo su
and then going into the /dev folder and enter your command (to save data into /dev/scull).
cd /dev
echo 54 > scull

How to display the execution result in remote linux screen(command input via ssh)?

everyone :
I need ssh to connect remote linux ,I already know how to run and display a GUI program in remote linux .It can be done by :
ssh username#ip
export DISPLAY=:0.0
firefox &
however ,my target linux hasn't X Window System , I need display the execution result in remote linux's screen ,for example :
my pc is A , remote pc is B
A use ssh access B , after connected to B ,I type ls in A then press enter
the execution result should display in B's screen (tty or whatever , I don't know what it should be called)
any idea? thanks for your help.
Basic idea:
a$ ssh user#b
b$ run-program >/dev/console
(I use a$ and b$ to indicate the shell prompts on A and B respectively.)
Problem with this:
b$ ls -l /dev/console
crw------- 1 root root 5, 1 Mar 19 09:10 /dev/console
Only root can write to /dev/console.
Possible workaround:
$b run-program | sudo tee /dev/console >/dev/null
(Redirecting to /dev/null here prevents the output from showing up on your screen as well.)
This does depend on user#b being allowed to run sudo tee /dev/console.
If you are sysadmin for B and user#b is not allowed to run sudo tee /dev/console, read man 5 sudoers and man 8 visudo to find out how to give user#b this permission.
If you are not sysadmin for B and user#b is not allowed to run sudo tee /dev/console, you will have to ask B's sysadmin to set this up for you.

Simulate a faulty block device with read errors?

I'm looking for an easier way to test my application against faulty block devices that generate i/o read errors when certain blocks are read. Trying to use a physical hard drive with known bad blocks is a pain and I would like to find a software solution if one exists.
I did find the Linux Disk Failure Simulation Driver which allows creating an interface that can be configured to generate errors when certain ranges of blocks are read, but it is for the 2.4 Linux Kernel and hasn't been updated for 2.6.
What would be perfect would be an losetup and loop driver that also allowed you to configure it to return read errors when attempting to read from a given set of blocks.
It's not a loopback device you're looking for, but rather device-mapper.
Use dmsetup to create a device backed by the "error" target. It will show up in /dev/mapper/<name>.
Page 7 of the Device mapper presentation (PDF) has exactly what you're looking for:
dmsetup create bad_disk << EOF
0 8 linear /dev/sdb1 0
8 1 error
9 204791 linear /dev/sdb1 9
EOF
Or leave out the sdb1 parts to and put the "error" target as the device for blocks 0 - 8 (instead of sdb1) to make a pure error disk.
See also The Device Mapper appendix from "RHEL 5
Logical Volume Manager Administration".
There's also a flakey target - a combo of linear and error that sometimes succeeds. Also a delay to introduce intentional delays for testing.
It seems like Linux's built-in fault injection capabilities would be a good idea to use.
Blog: http://blog.wpkg.org/2007/11/08/using-fault-injection/
Reference: https://www.kernel.org/doc/Documentation/fault-injection/fault-injection.txt
The easiest way to play with block devices is using nbd.
Download the userland sources from git://github.com/yoe/nbd.git and modify nbd-server.c to fail at reading or writing on whichever areas you want it to fail on, or to fail in a controllably random pattern, or basically anything you want.
I would like to elaborate on Peter Cordes answer.
In bash, setup an image on a loopback device with ext4, then write a file to it named binary.bin.
imageName=faulty.img
mountDir=$(pwd)/mount
sudo umount $mountDir ## make sure nothing is mounted here
dd if=/dev/zero of=$imageName bs=1M count=10
mkfs.ext4 $imageName
loopdev=$(sudo losetup -P -f --show $imageName); echo $loopdev
mkdir $mountDir
sudo mount $loopdev $mountDir
sudo chown -R $USER:$USER mount
echo "2ed99f0039724cd194858869e9debac4" | xxd -r -p > $mountDir/binary.bin
sudo umount $mountDir
in python3 (since bash struggles to deal with binary data) search for the magic binary data in binary.bin
import binascii
with open("faulty.img", "rb") as fd:
s = fd.read()
search = binascii.unhexlify("2ed99f0039724cd194858869e9debac4")
beg=0
find = s.find(search, beg); beg = find+1; print(find)
start_sector = find//512; print(start_sector)
then back in bash mount the faulty block device
start_sector=## copy value from variable start_sector in python
next_sector=$(($start_sector+1))
size=$(($(wc -c $imageName|cut -d ' ' -f1)/512))
len=$(($size-$next_sector))
echo -e "0\t$start_sector\tlinear\t$loopdev\t0" > fault_config
echo -e "$start_sector\t1\terror" >> fault_config
echo -e "$next_sector\t$len\tlinear\t$loopdev\t$next_sector" >> fault_config
cat fault_config | sudo dmsetup create bad_drive
sudo mount /dev/mapper/bad_drive $mountDir
finally we can test the faulty block device by reading a file
cat $mountDir/binary.bin
which produces the error:
cat: /path/to/your/mount/binary.bin: Input/output error
clean up when you're done with testing
sudo umount $mountDir
sudo dmsetup remove bad_drive
sudo losetup -d $loopdev
rm fault_config $imageName

Resources