Detect Ubuntu device as a MIDI keyboard/Interface in Windows - windows

I am creating a little experimentation application on my Odroid XU3 with Ubuntu 15.04 Lite.
http://dn.odroid.com/homebackup/201407071058089142.jpg
The device (Odroid) receives midi as input via a keyboard connected via one of the available USB Host ports (this part is OK) and sents some other midi instructions (also via USB, but USB OTG) to the computer to create harmony (this part is not ok).
The use case is :
you play on your midi keyboard some notes, the odroid received them, the embedded application code analyses them, find new notes (midi instructions) and send them to your Windows PC that you can root them to the VST of your choice.
The issue I have is that in order to achieve that, I need the Odroid device to appear as a MIDI keyboard in Windows that people can add the device in their Digital Audio Workstations.
Most of the midi controllers sold on the market have their own drivers but some are class compliant devices.
How can I make Windows detect this Odroid board an a midi keyboard? If I need to write a specific driver for that, from where to start?
Edit : Found g_midi drivers but not usb_f_midi
odroid#odroid:/lib/modules/3.10.72-23/kernel/drivers/usb/gadget$ ls -al
total 628
drwxr-xr-x 2 root root 4096 May 23 21:28 .
drwxr-xr-x 8 root root 4096 May 23 21:27 ..
-rw-r--r-- 1 root root 37544 May 23 21:11 g_acm_ms.ko
-rw-r--r-- 1 root root 17468 May 23 21:11 g_audio.ko
-rw-r--r-- 1 root root 24164 May 23 21:11 g_cdc.ko
-rw-r--r-- 1 root root 44488 May 23 21:11 g_ether.ko
-rw-r--r-- 1 root root 63552 May 23 21:11 g_ffs.ko
-rw-r--r-- 1 root root 16672 May 23 21:11 g_hid.ko
-rw-r--r-- 1 root root 37084 May 23 21:11 g_mass_storage.ko
-rw-r--r-- 1 root root 17468 May 23 21:11 g_midi.ko
-rw-r--r-- 1 root root 69752 May 23 21:11 g_multi.ko
-rw-r--r-- 1 root root 28164 May 23 21:11 g_ncm.ko
-rw-r--r-- 1 root root 35396 May 23 21:11 g_nokia.ko
-rw-r--r-- 1 root root 20944 May 23 21:11 g_printer.ko
-rw-r--r-- 1 root root 9016 May 23 21:11 g_serial.ko
-rw-r--r-- 1 root root 26628 May 23 21:11 g_webcam.ko
-rw-r--r-- 1 root root 11408 May 23 21:11 g_zero.ko
-rw-r--r-- 1 root root 25380 May 23 21:11 gadgetfs.ko
-rw-r--r-- 1 root root 45940 May 23 21:11 libcomposite.ko
-rw-r--r-- 1 root root 15244 May 23 21:11 u_serial.ko
-rw-r--r-- 1 root root 9972 May 23 21:11 usb_f_acm.ko
-rw-r--r-- 1 root root 8060 May 23 21:11 usb_f_obex.ko
-rw-r--r-- 1 root root 6928 May 23 21:11 usb_f_serial.ko
-rw-r--r-- 1 root root 14584 May 23 21:11 usb_f_ss_lb.ko
Second edit : Thanks to CL
Trying the g_midi driver
odroid#odroid:/proc/asound$ cat cards
0 [odroidaudio ]: odroid-audio - odroid-audio odroid-audio
1 [MPK225 ]: USB-Audio - MPK225 Akai MPK225 at usb-12110000.usb-1.2, full speed
2 [K61 ]: USB-Audio - Keystation 61 M-Audio Keystation 61 at usb-12110000.usb-1.3, full speed.
$ modprobe g_midi in_ports=1 out_ports=1
Error :
modprobe : ERROR : could not insert 'g_midi' : Device Or Ressource busy.
Same error with other ports (3,4, etc)
When removing the Midi keyboards :
odroid#odroid:/proc/asound$ cat cards
0 [odroidaudio ]: odroid-audio - odroid-audio odroid-audio
$ modprobe g_midi in_ports=1 out_ports=1
same error :
modprobe : ERROR : could not insert 'g_midi' : Device Or Ressource busy.

Just load the g_midi module:
$ modprobe g_midi in_ports=1 out_ports=1
(1 and 1 are the defaults.)
This will create a class-compliant USB MIDI interface, which is visible on the Odroid like a normal sound card:
$ cat /proc/asound/cards
0 [whatever ]: ...
1 [gmidi ]: MIDI Gadget - g_midi
MIDI Gadget
... and can be accessed with the normal Linux MIDI APIs.

Related

MacOS Catalina - Show all directories from root in Finder

As a reluctant Mac user, I am routinely frustrated by things that should be very simple. Finder is one of those. When trying to open an XML file from Firefox, I am asked what application I whish to open it with. Obviously MacVim. To do that, I need to navigate to /usr/local/bin/gvim which is a symlink to /Cellar, since it was installed with HomeBrew. However, when I select "Open with" and click "Choose", the Finder comes up and defaults to Applications. It's not in there, I just want to navigate directly to the symlink. Switching to "Macintosh HD" (also known as "/" to a more refined audience) only displays Application, Library, System, and Users. Where is everything else? Where is /usr, /bin, /etc? As a user, this seems disingenuous. It's not an accurate representation of my location in the filesystem. Sorry, this is a bit of a rant, but also a legitimate question. How do I display these all the time?
The UNIX (lowercase) directories are hidden from view, intentionally, through a special "hidden" flag. You can see those in ls -lO:
Chimera:~ morpheus$ ls -lO /
total 14
drwxrwxr-x+ 59 root admin sunlnk 1888 Sep 23 16:46 Applications
drwxr-xr-x+ 65 root wheel sunlnk 2080 Mar 20 2020 Library
drwxr-xr-x 2 root wheel hidden 64 Sep 30 2018 Network
drwxr-xr-x# 5 root wheel restricted 160 Sep 21 2018 System
drwxr-xr-x 7 root admin - 224 Mar 20 2020 Users
drwxr-xr-x# 8 root wheel hidden 256 Sep 23 21:17 Volumes
drwxr-xr-x# 37 root wheel restricted,hidden 1184 Mar 27 2019 bin
drwxrwxr-t# 2 root admin hidden 64 Feb 8 2019 cores
dr-xr-xr-x 3 root wheel hidden 4821 Aug 30 19:38 dev
lrwxr-xr-x# 1 root wheel restricted,hidden 11 Sep 30 2018 etc -> private/etc
dr-xr-xr-x 2 root wheel hidden 1 Sep 24 07:59 home
-rw-r--r-- 1 root wheel hidden,compressed 313 Aug 17 2018 installer.failurerequests
drwxr-xr-x 2 root wheel - 64 Oct 3 2018 mnt
drwxr-xr-x 2 root wheel - 64 Jan 21 2018 mnt1
dr-xr-xr-x 2 root wheel hidden 1 Sep 24 07:59 net
drwxr-xr-x 6 root wheel sunlnk,hidden 192 Sep 30 2018 private
drwxr-xr-x# 64 root wheel restricted,hidden 2048 Mar 27 2019 sbin
lrwxr-xr-x# 1 root wheel restricted,hidden 11 Sep 30 2018 tmp -> private/tmp
drwxr-xr-x# 9 root wheel restricted,hidden 288 Sep 21 2018 usr
lrwxr-xr-x# 1 root wheel restricted,hidden 11 Sep 30 2018 var -> private/var
Additionally, Finder will not display hidden "." files, the same way ls -l needs to be "persuaded" using -a (try "ls -lOa /", omitted here for brevity).
Pressing the apple key along with shift and '.' will display everything. To make this the default behavior:
defaults write com.apple.finder AppleShowAllFiles YES
In case you're interested in the rationale - it dates back to NeXTSTEP (the progenitor to MacOS X and later as we know it now), which wanted to provide a user interface to its own (Uppercase first letter) directories, while hiding those of the underlying UNIX (BSD layer), seeing as non-root users have nothing to look for there, anyway (and most users have no knowledge of terminal/shell).

Developing inside docker on WSL2-Ubuntu from vscode

I am trying run docker inside WSL (am running Ubuntu in WSL). Also am new to docker. The doc says:
To get the best out of the file system performance when bind-mounting files:
Store source code and other data that is bind-mounted into Linux containers (i.e., with docker run -v <host-path>:<container-path>) in the Linux filesystem, rather than the Windows filesystem.
Linux containers only receive file change events (“inotify events”) if the original files are stored in the Linux filesystem.
Performance is much higher when files are bind-mounted from the Linux filesystem, rather than remoted from the Windows host. Therefore avoid docker run -v /mnt/c/users:/users (where /mnt/c is mounted from Windows).
Instead, from a Linux shell use a command like docker run -v ~/my-project:/sources <my-image> where ~ is expanded by the Linux shell to $HOME.
I also came across following:
Run sudo docker run -v "$HOME:/host" --name "[name_work]" -it docker.repo/[name]. With, [$HOME:/host], you can access your home directory in /host dir in docker image. This allows you to access your files on the local machine inside the docker. So you can edit your source code in your local machine using your favourite editor and run them directly inside the docker. Make sure that you have done this correct. Otherwise, you may need to copy files from the local machine to docker, for each edit (a painful job).
I am not able to understand the format of parameter passed to -v option and what it does. I am thinking that it will allow to access Ubuntu directories inside docker. So $HOME:/host will map Ubuntu's home directory to /host inside.
Q1. But what is /host?
Q2. Can I do what is stated by above two quotes together? I mean what they are saying is compatible? I guess yes. What all its saying is I should not mount from windows director like /mnt/<driveletter>/.... If I am mounting linux directory like $USER/... then it will give better performance, right?
I tried out running it to understand it:
~$ docker run -v "$HOME:/host" --name "mydokr" -it docker.repo.in/dokrimg
root#f814974a1cfb:/home# ls
root#f814974a1cfb:/home# ll
total 8
drwxr-xr-x 2 root root 4096 Apr 15 11:09 ./
drwxr-xr-x 1 root root 4096 Sep 22 07:16 ../
root#f814974a1cfb:/home# pwd
/home
root#f814974a1cfb:/home# cd ..
root#f814974a1cfb:/# ll
total 64
drwxr-xr-x 1 root root 4096 Sep 22 07:16 ./
drwxr-xr-x 1 root root 4096 Sep 22 07:16 ../
-rwxr-xr-x 1 root root 0 Sep 22 07:16 .dockerenv*
lrwxrwxrwx 1 root root 7 Jul 3 01:56 bin -> usr/bin/
drwxr-xr-x 2 root root 4096 Apr 15 11:09 boot/
drwxr-xr-x 5 root root 360 Sep 22 07:16 dev/
drwxr-xr-x 1 root root 4096 Sep 22 07:16 etc/
drwxr-xr-x 2 root root 4096 Apr 15 11:09 home/
drwxr-xr-x 5 1000 1001 4096 Sep 22 04:52 host/
lrwxrwxrwx 1 root root 7 Jul 3 01:56 lib -> usr/lib/
lrwxrwxrwx 1 root root 9 Jul 3 01:56 lib32 -> usr/lib32/
lrwxrwxrwx 1 root root 9 Jul 3 01:56 lib64 -> usr/lib64/
lrwxrwxrwx 1 root root 10 Jul 3 01:56 libx32 -> usr/libx32/
drwxr-xr-x 2 root root 4096 Jul 3 01:57 media/
drwxr-xr-x 2 root root 4096 Jul 3 01:57 mnt/
drwxr-xr-x 2 root root 4096 Jul 3 01:57 opt/
dr-xr-xr-x 182 root root 0 Sep 22 07:16 proc/
drwx------ 1 root root 4096 Aug 24 03:54 root/
drwxr-xr-x 1 root root 4096 Aug 11 10:24 run/
lrwxrwxrwx 1 root root 8 Jul 3 01:56 sbin -> usr/sbin/
drwxr-xr-x 2 root root 4096 Jul 3 01:57 srv/
dr-xr-xr-x 11 root root 0 Sep 22 03:32 sys/
-rw-r--r-- 1 root root 1610 Aug 24 03:56 test_logPath.log
drwxrwxrwt 1 root root 4096 Aug 24 03:57 tmp/
drwxr-xr-x 1 root root 4096 Aug 11 10:24 usr/
drwxr-xr-x 1 root root 4096 Jul 3 02:00 var/
root#f814974a1cfb:/home# cd ../host
root#f814974a1cfb:/host# ll
total 36
drwxr-xr-x 5 1000 1001 4096 Sep 22 04:52 ./
drwxr-xr-x 1 root root 4096 Sep 22 07:16 ../
-rw-r--r-- 1 1000 1001 220 Sep 22 03:38 .bash_logout
-rw-r--r-- 1 1000 1001 3771 Sep 22 03:38 .bashrc
drwxr-xr-x 3 1000 1001 4096 Sep 22 04:56 .docker/
drwxr-xr-x 2 1000 1001 4096 Sep 22 03:38 .landscape/
-rw-r--r-- 1 1000 1001 0 Sep 22 03:38 .motd_shown
-rw-r--r-- 1 1000 1001 921 Sep 22 04:52 .profile
-rw-r--r-- 1 1000 1001 0 Sep 22 03:44 .sudo_as_admin_successful
drwxr-xr-x 5 1000 1001 4096 Sep 22 04:52 .vscode-server/
-rw-r--r-- 1 1000 1001 183 Sep 22 04:52 .wget-hsts
So I am not getting whats happening here. I know docker has its own file system.
Q3. Is is that, what am finding at /home and /host is indeed container's own file system?
Q4. Also, what happened to -v $HOME:/host here?
Q5. How can I do as stated by 2nd quote:
This allows you to access your files on the local machine inside the docker. So you can edit your source code in your local machine using your favourite editor and run them directly inside the docker.
Q6. How do I connect vscode to this container? From WSL-Ubuntu, I could just run code . to launch vscode. But the same does not seem to work here:
root#f814974a1cfb:/home# code .
bash: code: command not found
This link says:
A devcontainer.json file can be used to tell VS Code how to configure the development container, including the Dockerfile to use, ports to open, and extensions to install in the container. When VS Code finds a devcontainer.json in the workspace, it automatically builds (if necessary) the image, starts the container, and connects to it.
But I guess this says starting up creating new container form vscode. But not connecting to already existing container. I am not able to find my dockercontainer.json. I downloaded this container image using docker pull.

Force rotate a certain log file without using logrotate

I am trying to force rotate a specific log, e.g., /mroot/etc/mlog/sktrace.log.
For example, currently here are all the logs related to sktrace:
<machine_name>% ll /mroot/etc/mlog/sktrace*
-rw-r--r-- 2 root wheel 13276789 Oct 16 13:00 /mroot/etc/mlog/sktrace.log
-rw-r--r-- 1 root wheel 3063670 Oct 13 10:42 /mroot/etc/mlog/sktrace.log.0000000001
-rw-r--r-- 1 root wheel 44072508 Oct 14 10:42 /mroot/etc/mlog/sktrace.log.0000000002
-rw-r--r-- 1 root wheel 96622284 Oct 15 10:42 /mroot/etc/mlog/sktrace.log.0000000003
-rw-r--r-- 1 root wheel 104858396 Oct 16 08:54 /mroot/etc/mlog/sktrace.log.0000000004
-rw-r--r-- 1 root wheel 10466192 Oct 16 10:42 /mroot/etc/mlog/sktrace.log.0000000005
-rw-r--r-- 2 root wheel 13276789 Oct 16 13:00 /mroot/etc/mlog/sktrace.log.0000000006
By “force rotate”, I mean to copy the content in the current /mroot/etc/mlog/sktrace.log to /mroot/etc/mlog/sktrace.log.0000000007, and then truncate /mroot/etc/mlog/sktrace.log to 0-byte.
The decent way is probably via logrotate. But it is not available on the system I am using:
<machine_name>% which logrotate
logrotate: Command not found.
<machine_name>% ll /usr/sbin/logrotate
ls: /usr/sbin/logrotate: No such file or directory
What's the best alternative in bash, please?

What directories does Linux have that macOS doesn't?

I'm a Python programmer that is trying to make a system of sorts that creates save data for a game I'm making, and I want it to be in different places in something like Ubuntu than I do macOS. As I don't have a macOS, and it's impossible to just up and get an ISO to get a macOS VM, I can't look through the files and folders and see what it has (or doesn't) that Linux does or doesn't.
I've tried looking all over to the point of attempting to get a hold of an ISO to build a VM in VirtualBox, but haven't been successful at all.
What files or folders does macOS have that Linux does, or vice versa?
To complete the (excellent) answer from #Michael, here is the listing of the home and root directory after a fresh install on the latest stable release of MacOS System (10.14.2)
MacBook-Pro:~ max$ ls -al /
total 37
drwxr-xr-x 26 root wheel 832 Jan 6 19:00 .
drwxr-xr-x 26 root wheel 832 Jan 6 19:00 ..
-rw-rw-r-- 1 root admin 8196 Jan 13 07:11 .DS_Store
drwx------ 5 root admin 160 Jan 6 11:47 .Spotlight-V100
d-wx-wx-wt 2 root wheel 64 Jan 14 06:39 .Trashes
---------- 1 root admin 0 Aug 18 06:53 .file
drwx------ 11 root admin 352 Jan 14 06:39 .fseventsd
drwxr-xr-x 2 root wheel 64 Aug 18 06:53 .vol
drwxrwxr-x+ 39 root admin 1248 Nov 30 12:49 Applications
drwxr-xr-x+ 60 root wheel 1920 Nov 30 12:50 Library
drwxr-xr-x 2 root wheel 64 Aug 18 06:53 Network
drwxr-xr-x# 5 root wheel 160 Nov 30 12:46 System
drwxr-xr-x 5 root admin 160 Jan 6 18:59 Users
drwxr-xr-x+ 4 root wheel 128 Jan 14 06:39 Volumes
drwxr-xr-x# 37 root wheel 1184 Nov 30 12:55 bin
drwxrwxr-t 2 root admin 64 Aug 18 06:53 cores
dr-xr-xr-x 3 root wheel 4301 Jan 14 06:39 dev
lrwxr-xr-x# 1 root wheel 11 Jan 6 18:49 etc -> private/etc
dr-xr-xr-x 2 root wheel 1 Jan 14 06:40 home
-rw-r--r-- 1 root wheel 313 Aug 18 10:03 installer.failurerequests
dr-xr-xr-x 2 root wheel 1 Jan 14 06:40 net
drwxr-xr-x 6 root wheel 192 Nov 30 12:50 private
drwxr-xr-x# 64 root wheel 2048 Jan 6 18:49 sbin
lrwxr-xr-x# 1 root wheel 11 Jan 6 18:49 tmp -> private/tmp
drwxr-xr-x# 9 root wheel 288 Nov 30 12:38 usr
lrwxr-xr-x# 1 root wheel 11 Jan 6 18:49 var -> private/var
And the home dir:
MacBook-Pro:~ max$ ls -al ~
total 16
drwxr-xr-x+ 15 max staff 480 Jan 14 06:43 .
drwxr-xr-x 5 root admin 160 Jan 6 18:59 ..
-r-------- 1 max staff 7 Jan 6 18:59 .CFUserTextEncoding
drwx------ 2 max staff 64 Jan 14 06:40 .Trash
-rw------- 1 max staff 0 Jan 13 07:11 .bash_history
drwx------ 10 max staff 320 Jan 14 06:40 .bash_sessions
-rw------- 1 max staff 908 Jan 14 06:43 .viminfo
drwx------+ 3 max staff 96 Jan 6 18:59 Desktop
drwx------+ 3 max staff 96 Jan 6 18:59 Documents
drwx------+ 3 max staff 96 Jan 6 18:59 Downloads
drwx------# 51 max staff 1632 Jan 13 07:11 Library
drwx------+ 3 max staff 96 Jan 6 18:59 Movies
drwx------+ 3 max staff 96 Jan 6 18:59 Music
drwx------+ 3 max staff 96 Jan 6 18:59 Pictures
drwxr-xr-x+ 4 max staff 128 Jan 6 18:59 Public
Application settings on macOS are ususally saved somewhere in ~/Library: Common places are ~/Library/Preferences/com.example.mycoolgame.plist for preferences (should be in plist format and "com.example.mycoolgame" should be a valid bundle ID that you own (you should own the domain)). The advantage/disadvantage of this path is that power users know about this directory and can edit the files there as they wish.
Then you have ~/Library/Caches for cached data. All cached data should be put somewhere under this directory. (Never use it for content that cannot be regenerated or redownloaded though.)
~/Library/ApplicationSupport/YourApplicationName/...: here you can basically do anything you like. It would be good if "YourApplicationName" would be globally unique in this case.. So better make it long. Users usually don't see the filesystem contents of anything below "~/Library", so there is no need for short names.
Of course, you can also put your savegames in ~/Documents/MyCoolGame/savegames and tell the user that you save the games there.
A gotcha (maybe): I'm not sure if system APIs expand "~" properly. I think probably not: Calling fopen with a path that starts with "~" would most likely not do the right thing. The users directory is located at something like "/Users/max", so "~" expands to "/Users/max" in the command line if the username is "max".
I can't answer your original question "What directories does Linux have that macOS doesn't?" because I don't have a Linux box at hand at the moment, and I don't think that it would be helpful for your use case.
For global data, there is also the "/Library" hierarchy.. But normal users don't have access to this place, so your game would need to ask for admin rights, which will make everything much more complicated, and this will feel user-unfriendly to macOS users. The macOS way is to have a self-contained application bundle and put all user-specific or temporary data into the appropriate place within the users home folder.

Access GPIO (/sys/class/gpio) as non-root

The /sys/class/gpio can only be accessed as root by default. So I like that a new group gpio can use the files and directories under /sys/class/gpio. To achieve that I added the following lines to /etc/rc.local (I'm on Debian):
sudo chown root:gpio /sys/class/gpio/unexport /sys/class/gpio/export
sudo chmod 220 /sys/class/gpio/unexport /sys/class/gpio/export
So this gives write permissions to all the gpio group members. So they can now export and unexport pins fine.
The problem is they can't read/write the specific pin files after export (e.x. /sys/class/gpio/gpio17) beacause those are owned by root:root again.
How can I change that they are created by default as root:gpio too? I mean I can do that manually each time I export a pin. But that's a bit uncomfy.
UPDATE
According to larsks' answer I created the missing rule file. Now it partially works:
-rwxrwx--- 1 root gpio 4096 Jun 19 16:48 export
lrwxrwxrwx 1 root gpio 0 Jun 19 16:51 gpio17 -> ../../devices/soc/3f200000.gpio/gpio/gpio17
lrwxrwxrwx 1 root gpio 0 Jun 19 16:45 gpiochip0 -> ../../devices/soc/3f200000.gpio/gpio/gpiochip0
-rwxrwx--- 1 root gpio 4096 Jun 19 16:45 unexport
But for the ./gpio17/ I still get root:root:
-rw-r--r-- 1 root root 4096 Jun 19 16:52 active_low
lrwxrwxrwx 1 root root 0 Jun 19 16:52 device -> ../../../3f200000.gpio
-rw-r--r-- 1 root root 4096 Jun 19 16:52 direction
-rw-r--r-- 1 root root 4096 Jun 19 16:52 edge
drwxr-xr-x 2 root root 0 Jun 19 16:52 power
lrwxrwxrwx 1 root root 0 Jun 19 16:52 subsystem -> ../../../../../class/gpio
-rw-r--r-- 1 root root 4096 Jun 19 16:52 uevent
-rw-r--r-- 1 root root 4096 Jun 19 16:52 value
UPDATE 2
Okay I solved the problem. Because I installed Raspbian over the RaspbianInstaller I never went through the raspi-config tool. This seems to be a problem. Because I was also missing the /sys/device/virtual/gpio/ folder.
I followed this guide here: https://community.element14.com/products/raspberry-pi/f/forum/26425/piface-digital-2---setup-and-use#139528
And afterwards the permissions were correct (even for the pin-folders and their files value, direction, ...).
More common rule for 4.x kernels will be the following
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'find -L /sys/class/gpio/ -maxdepth 2 -exec chown root:gpio {} \; -exec chmod 770 {} \; || true'"
The rule in the initial answer will fail to chown the exported gpio if there's a symbolic link in the path
UPD please beg in mind that when you export some GPIO via sysfs, you should wait for udev rule to fire and complete before you get desired access rights. The thing that worked for me was sleep about 100ms before trying to access GPIO files.
You can do this using udev rules, which can define actions to execute when the kernel instantiates new devices. Current versions of the Raspbian distribution for Raspberry Pi devices contain the following in /etc/udev/rules.d/99-com.rules:
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio; chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio'"
This ensures that entries under /sys/class/gpio are always available to members of the gpio group:
# ls -lL /sys/class/gpio/
total 0
-rwxrwx--- 1 root gpio 4096 May 6 23:36 export
drwxrwx--- 2 root gpio 0 Jan 1 1970 gpiochip0
-rwxrwx--- 1 root gpio 4096 May 6 23:37 unexport
# echo 11 > /sys/class/gpio/export
# ls -lL /sys/class/gpio/
total 0
-rwxrwx--- 1 root gpio 4096 May 6 23:37 export
drwxrwx--- 2 root gpio 0 May 6 23:37 gpio11
drwxrwx--- 2 root gpio 0 Jan 1 1970 gpiochip0
-rwxrwx--- 1 root gpio 4096 May 6 23:37 unexport
Update
Permissions are correct for individual pins as well:
# ls -Ll /sys/class/gpio/gpio11/
total 0
-rwxrwx--- 1 root gpio 4096 May 6 23:37 active_low
drwxr-xr-x 3 root root 0 May 6 23:36 device
-rwxrwx--- 1 root gpio 4096 May 6 23:37 direction
-rwxrwx--- 1 root gpio 4096 May 6 23:37 edge
drwxrwx--- 2 root gpio 0 May 6 23:37 subsystem
-rwxrwx--- 1 root gpio 4096 May 6 23:37 uevent
-rwxrwx--- 1 root gpio 4096 May 6 23:37 value
Expanding on the answer by #roman-savrulin, here's a simpler version.
There's no need to run the rule on REMOVE events, only ADD events. There's also no need to run 'find' as the udev environment will supply the exact path of the sysfs directory containing the new GPIO pin's files. You can also use 'chgrp' to change only the owning group, and symbolic modes in 'chmod' to only add the group-write permission bit.
You'll still have to wait for the completion of the rule processing before trying to open the pin's files, but the process should complete more quickly with a simpler rule which only touches the minimum number of files necessary.
SUBSYSTEM=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c 'chgrp -R gpio /sys/${DEVPATH} && chmod -R g+w /sys/${DEVPATH}'"
Check the groups you belong to:
userk#dopamine $: groups
userk sudo dialout
If you belong to dialout the following, if not, comment.
userk#dopamine $: ls -l /dev/gpiomem
crw------- root root /dev/gpiomem
This file mirrors the memory associated with the GPIO device. The output of the command means that the owner of the file is the root user and the group that "owns" it is the root group. The 10 characters represent the file type and the permissions associated with it. The current configuration allows the owner of the file to read and write to the file.
You want to be able to read and write that file if you want to control the gpios.
One option would be to modify the group owner and make it match with the one you belong to (dialout in my case) and set the permissions in order to allow all users of that group to read and write the file.
Long story short:
userk#dopamine $: sudo chown root:dialout /dev/gpiomem
userk#dopamine $: sudo chmod 660 /dev/gpiomem
Wait! This setting won't be persistent and will vanish after reboot.
See this post for further info about the topic
For Ubuntu run.
sudo apt install rpi.gpio-common

Resources