This system image was built using the Yocto Project (Kirkstone branch) for the Raspberry Pi 4 (64-bit) target.
It includes the following key packages and configurations:
SSH— for remote accessWiFi— for supporting wireless connectivityNano editor— for basic text editingQt5— for GUI application developmentRPI— for screen mirroring for MAC OS, andscrcpy— for screen mirroring for Android OSALSA— for audio playingHello Application— native C++ application
this project is built using kernel version 5.15.x and uses systemd as the init system
I will follow this architecture overview
Free Disk— you need a system with at least 90 Gbytes of free disk spaceRAM— to build an image, you need at least 8 Gbytes of RAMYOCTO- current release Kirkstone supported in Ubuntu 20.04 and Ubuntu 22.04
-
- Layer in Yocto is a modular collection of metadata that defines part of your Linux build
- In technically definition layer is a directory containing BitBake metadata such as
- Recipes (.bb)
- Classes (.bbclass)
- Configuration files (.conf)
- Layers type
BSP Layer- provides all hardware-specific support needed to run Linux on a target board. It defines how the kernel, bootloader, and device drivers are built and configured for a specific SoC (like meta-raspberrypi)SW Layer- contains higher-level software components that are independent of the hardware. It’s used to add or customize packages, applications, libraries, and services that run on top of the system (like meta-qt5)Distribution Layer- defines policies and settings that determine how the overall system behaves and is built. It provides a higher-level configuration that specifies which layers to include, which init system to use, and how images should be composed (like poky)
-
- Recipe tells BitBake how to build a specific piece of software or system component
- Recipes type
Package Recipe- Purpose : Build and install a single software package
- Description : package recipe tells how to fetch, compile, and install a specific software component. It defines dependencies, source location, build instructions, and install rules.
Image Recipe- Purpose : Define the final root filesystem image
- Description : An image recipe specifies which packages and configurations should be included in the final system image.
Class Recipe- Purpose : Define common reusable behavior shared between multiple recipes
- Description : class recipe (.bbclass file) acts like a template or helper that contains common functions, tasks, and variable definitions.
Configuration Recipe- Purpose : Define global build settings, machine configurations, and distribution policies.
- Description : Configuration files tell BitBake how to build the system rather than what to build. They live in .conf files (not .bb) and define settings for:
- machine (hardware-specific)
- distro (distribution-wide)
- layer (metadata paths)
- local build environment
- Common files:
- local.conf → your build-specific settings (set in build/conf/)
- bblayers.conf → lists which layers are included
- machine.conf → defines hardware (e.g., MACHINE = "raspberrypi4")
- distro.conf → defines global policies (e.g., init system, package manager)
-
Package recipe life cycle
Development is divided into phases to facilitate Development process
Here, prepare the host machine to be ready to create an image using YOCTO
-
Install Yocto dependencies
sudo apt install gawk wget git diffstat unzip texinfo gcc build-essential chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev python3-subunit mesa-common-dev zstd liblz4-tool file locales libacl1 sudo locale-gen en_US.UTF-8
-
Choose YOCTO Release
Here, I will use Kirkstone version
You can see more about releases link.
-
Clone Poky Kirkstone version
To clone Poky, run this command in the path you want (will assume that current path is ~/YOCTO and will run following command)git clone -b kirkstone https://github.com/yoctoproject/poky
So, poky path is ~/YOCTO/poky
-
Understand Poky
Poky is the reference distribution of the Yocto Project — it’s not a Linux distribution itself, but rather a build system (based on BitBake) and a set of metadata that allow you to build your own custom Linux distribution.
Bitbake— The build engine — parses recipes, resolves dependencies, and executes build tasks.Metadata- Describe what to build and how to build it. This includes recipes (.bb), classes (.bbclass), and configuration files (.conf).OpenEmbedded- The core layer that provides the essential Linux components and build metadataMetadata-poky- Poky-specific configuration layer
Here, I will integrate and create all recipes needed to create an image
-
Integrate BSP layer for Raspberry Pi 4 Go to
search for meta-raspberrypi and choose it
Here, look at the repo link
This is confirmation that this BSP will provide full functionality for my HW
cd ~/YOCTO/poky git clone -b kirkstone git://git.yoctoproject.org/meta-raspberrypi source oe-init-build-env bitbake-layers add-layer ../meta-raspberrypi/
this is test image provided you can use it to test that HW work right
you need to change machine that will create image for
cd cd ~/YOCTO/poky/build/conf vi local.conf # change MACHINE variable from qemuarm64 to raspberrypi4-64 to be final MACHINE ??= "raspberrypi4-64" # in same file add following lines that control number of core used during running build engine(bitbake) this mean that I will use 8 cores from CPu as I have 12 core you can know number of cores you have $lscpu BB_NUMBER_THREADS="8" PARALLEL_MAKE="-j 8"
will run this command to confirm the generation image is complete without problem
bitbake rpi-test-image
-
Integrate SW layer (Qt-5) Go to
search for meta-qt5 and choose it
Here, look at the repo link and Dependencies
cd ~/YOCTO/poky git clone -b kirkstone https://github.com/meta-qt5/meta-qt5.git cd ~/YOCTO/poky/build bitbake-layers add-layer ../meta-qt5/
during run command bitbake-layers add-layer ../meta-qt5/ will face this error
explain how this error introduced
So, will clone openEmbedded-core
cd ~/YOCTO/poky git clone -b kirkstone git://git.openembedded.org/meta-openembedded cd ~/YOCTO/poky/meta-openembedded ls
will find that it consists of multiple layers
From Dependencies for Qt5 we only interested meta-oe layer
cd ~/YOCTO/poky/build bitbake-layers add-layer meta-openembedded/meta-oe bitbake-layers add-layer ../meta-qt5/
-
Create SW Layer
This layer will be used to integrate all layers. Follow the next command lines to create a layer and add it to bblayers.conf
cd ~/YOCTO/poky bitbake-layers create-layer meta-ivi cd ~/YOCTO/poky/build bitbake-layers add-layer ../meta-ivi/
-
Create Distro Layer
to define the type of init system. What are init systems? When Linux boots, the init system is the first process started by the kernel (PID 1). Its job is to:
- Initialize the system
- Start essential background services (daemons)
- Manage processes
- Handle shutdown and reboot So I will create two Distro layers meta-info-distro that will use systemd and meta-audio-distro that will use systemv
cd ~/YOCTO/poky bitbake-layers create-layer meta-info-distro bitbake-layers create-layer meta-audio-distro cd ~/YOCTO/poky/build bitbake-layers add-layer ../meta-info-distro/ bitbake-layers add-layer ../meta-audio-distro/
As we know, Layer is a directory, and to make it a Distro layer, you need to have a specific folder structure so will take Poky layer structure as an example
So fucos in this image to this folder distro and need to have same to new two distro layer
meta-poky/ ├──conf | ├── distro/ | |└── include/ | |└──layer.conf
Let's prepare info distro
cd ~/YOCTO/poky/meta-info-distro/conf mkdir distro cd distro/ mkdir include touch infotainment.conf cd include/ touch systemd.inc
content of infotainment.conf
DISTRO="infotainment" DISTRO_NAME="Bullet-Infotainment" DISTRO_VERSION="1.0" MAINTAINER="heshamgamal.a.h@gmail.com" # SDK Information. SDK_VENDOR = "-bulletSDK" SDK_VERSION = "${@d.getVar('DISTRO_VERSION').replace('snapshot-${METADATA_REVISION}', 'snapshot')}" SDK_VERSION[vardepvalue] = "${SDK_VERSION}" SDK_NAME = "${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}" # Installation path --> can be changed to ${HOME}-${DISTRO}-${SDK_VERSION} SDKPATHINSTALL = "/opt/${DISTRO}/${SDK_VERSION}" # Disribution Feature --> NOTE: used to add customize package (for package usage). # infotainment --> INFOTAINMENT INFOTAINMENT_DEFAULT_DISTRO_FEATURES = "largefile opengl ptest multiarch vulkan x11 bluez5 bluetooth wifi qt5" INFOTAINMENT_DEFAULT_EXTRA_RDEPENDS = "packagegroup-core-boot" INFOTAINMENT_DEFAULT_EXTRA_RRECOMMENDS = "kernel-module-af-packet" # TODO: to be org. DISTRO_FEATURES ?= "${DISTRO_FEATURES_DEFAULT} ${INFOTAINMENT_DEFAULT_DISTRO_FEATURES} userland" #add systemd as init-process require conf/distro/include/systemd.inc # prefered version for packages. PREFERRED_VERSION_linux-yocto ?= "5.15%" PREFERRED_VERSION_linux-yocto-rt ?= "5.15%" # Build System configuration. LOCALCONF_VERSION="2" # add poky sanity bbclass INHERIT += "poky-sanity"
content of systemd.inc
#install systemd as default init system manager DISTRO_FEATURES:append=" systemd" # select systemd as init manager VIRTUAL-RUNTIME_init_manager="systemd" VIRTUAL-RUNTIME_initscripts="systemd-compat-units"
This Distro will have the following Features
Here, define the Linux version
Here, include part responsible for define init process system
Let's prepare audio distro
cd ~/YOCTO/poky/meta-audio-distro/conf mkdir distro cd distro/ touch audio.conf
content of audio.conf
DISTRO="audio" DISTRO_NAME="Bullet-audio" DISTRO_VERSION="1.0" MAINTAINER="heshamgamal.a.h@gmail.com" # SDK Information. SDK_VENDOR = "-bulletSDK" SDK_VERSION = "${@d.getVar('DISTRO_VERSION').replace('snapshot-${METADATA_REVISION}', 'snapshot')}" SDK_VERSION[vardepvalue] = "${SDK_VERSION}" SDK_NAME = "${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}" # Installation path --> can be changed to ${HOME}-${DISTRO}-${SDK_VERSION} SDKPATHINSTALL = "/opt/${DISTRO}/${SDK_VERSION}" # Disribution Feature --> NOTE: used to add customize package (for package usage). # infotainment --> INFOTAINMENT AUDIO_DEFAULT_DISTRO_FEATURES = "largefile opengl ptest multiarch vulkan bluez5 bluetooth wifi audio_only" AUDIO_DEFAULT_EXTRA_RDEPENDS = "packagegroup-core-boot" AUDIO_DEFAULT_EXTRA_RRECOMMENDS = "kernel-module-af-packet" # TODO: to be org. DISTRO_FEATURES ?= "${DISTRO_FEATURES_DEFAULT} ${AUDIO_DEFAULT_DISTRO_FEATURES} userland" # prefered version for packages. PREFERRED_VERSION_linux-yocto ?= "5.15%" PREFERRED_VERSION_linux-yocto-rt ?= "5.15%" # Build System configuration. LOCALCONF_VERSION="2" # add poky sanity bbclass INHERIT += "poky-sanity"
This Distro will have the following Features
I will use the same Linux version, and by default systemv used
-
Inside meta-ivi layer will add different types of recipes to create my own Image recipe
-
Add a Native Cpp application
cd ~/YOCTO/poky/meta-ivi mkdir recipes-native-cpp cd recipes-native-cpp/ mkdir helloworldd
I will use recipetool to get code from upstream
cd ~/YOCTO/poky/meta-ivi/recipes-native-cpp/helloworldd recipetool create -o worldhello_1.1.bb https://github.com/embeddedlinuxworkshop/y_t1.git
What is the final folder structure for the new package recipe?
So, why was this recipe created with this structure meta-ivi/recipes-native-cpp/helloworldd
Final content to the recipe to build it without problems
# Recipe created by recipetool # This is the basis of a recipe and may need further editing in order to be fully functional. # (Feel free to remove these comments when editing.) # TODO 1. Documentation varaibles SUMMARY = "Hello World example in C++" DESCRIPTION = "A simple C++ Hello World example" #use it if the # HOMEPAGE = "https://github.com/embeddedlinuxworkshop/y_t1" # Unable to find any files that looked like license statements. Check the accompanying # documentation and source headers and set LICENSE and LIC_FILES_CHKSUM accordingly. # # NOTE: LICENSE is being set to "CLOSED" to allow you to at least start building - if # this is not accurate with respect to the licensing of the software being built (it # will not be in most cases) you must specify the correct value before using this # recipe for anything other than initial testing/development! # # TODO 2 License Varaibles . LICENSE = "CLOSED" LIC_FILES_CHKSUM = "" # TODO 3. Source code varaibles SRC_URI = "git://github.com/embeddedlinuxworkshop/y_t1.git;protocol=https;branch=master" # Modify these as desired PV = "1.1+git${SRCPV}" SRCREV = "49600e3cd69332f0e7b8103918446302457cd950" S = "${WORKDIR}/git" # TODo 4. Tasks to be executed # NOTE: no Makefile found, unable to determine what needs to be done do_configure () { # Specify any needed configure commands here : } do_compile () { # Specify compilation commands here $CXX ${S}/main.cpp -o worldhello } do_install () { # manp ---> ${WOPRKDIR}/image # specify install commands here # 1. create directory ${WOPRKDIR}/image/usr/bin install -d ${D}/${bindir} # 2. install worldhello binary to ${WOPRKDIR}/image/usr/bin install -m 0755 worldhello ${D}/${bindir} } # ignore do_package do_package_qa[noexec] = "1"
Run the following command to build
bitbake worldhelllo
-
Create my own Recipe Image An image recipe (*.bb) defines the final root filesystem (image) that Yocto will build — that is, the actual system that runs on your target(Raspberry Pi 4).Unlike a package recipe (which builds a single app or library), an image recipe tells Yocto:“What packages should be installed into the final image, and how should it be built and formatted (ext4, wic, sdcard, etc.).”
To create your own image recipe there is Base should start from it. Will use core-image-sato as base
There is standard structure for Image. currently I will create this structure
cd ~/YOCTO/poky/meta-ivi mkdir recipes-core cd recipes-core/ mkdir images cd images/ touch ivi-test-image.bb
content of ivi-test-image.bb will include (native cpp application) IMAGE_INSTALL is a variable used in image recipes (*.bb) to tell Yocto which packages should be included inside the final root filesystem image that will run on your device
# 1. include base image require recipes-sato/images/core-image-sato.bb # 2. set of local varaibles SUMMARY = "A simple IVI test image that include rpi function + helloworld package recipe" # 3. IMAGE_INSTALL IMAGE_INSTALL:append = " worldhello"
Confirm that everything work right
bitbake ivi-test-image
-
Integrate SSH and be able to access root through SSH using empty password There are two variables. I think there is need to provide clear define for them
IMAGE_FEATURES- is a variable used to define a set of high-level features or attributes that an image should possess. These features, when specified, instruct the Yocto build system to automatically include the necessary packages, configurations, or modifications to achieve the desired functionality in the final image.IMAGE_INSTALL- is a variable used in image recipes (*.bb) to tell Yocto which packages should be included inside the final root filesystem image that will run on your deviceso to do this will update ivi-test-image content
# 1. include base image require recipes-sato/images/core-image-sato.bb # 2. set of local varaibles SUMMARY = "A simple IVI test image that include rpi function + helloworld package recipe" # 3. IMAGE_INSTALL IMAGE_INSTALL:append = " worldhello openssh dhcpcd net-tools" # 4. IMAGE_FEATURES # 1. install ssh # 2. allow root access through ssh # 3. access root through ssh using empty password IMAGE_FEATURES:append = " debug-tweaks ssh-server-openssh"
-
Integrate Nano Editor to be able to open any file and edit on the target machine
will move to Link
Press in link to Instruction link
will find that Nano has prerequisites
And there is dependency I need to resolve to compile without problems
To create package recipe will use recipetool
cd ~/YOCTO/poky/meta-ivi mkdir recipes-editor cd recipes-editor mkdir nano cd nano recipetool create -o nano_1.0.bb https://git.savannah.gnu.org/git/nano.git
this final content to nano_1.0.bb
# Recipe created by recipetool # This is the basis of a recipe and may need further editing in order to be fully functional. # (Feel free to remove these comments when editing.) # WARNING: the following LICENSE and LIC_FILES_CHKSUM values are best guesses - it is # your responsibility to verify that the values are complete and correct. # # The following license files were not able to be identified and are # represented as "Unknown" below, you will need to check them yourself: # COPYING.DOC # # NOTE: multiple licenses have been detected; they have been separated with & # in the LICENSE value for now since it is a reasonable assumption that all # of the licenses apply. If instead there is a choice between the multiple # licenses then you should change the value to separate the licenses with | # instead of &. If there is any doubt, check the accompanying documentation # to determine which situation is applicable. LICENSE = "GPL-3.0-only & Unknown" LIC_FILES_CHKSUM = "file://COPYING;md5=f27defe1e96c2e1ecd4e0c9be8967949 \ file://COPYING.DOC;md5=ad1419ecc56e060eccf8184a87c4285f" SRC_URI = "git://git.savannah.gnu.org/git/nano.git/;protocol=https;branch=master" # Modify these as desired PV = "1.0+git${SRCPV}" SRCREV = "50e186bc8162009c9efeb562d29f9aae70406eb4" S = "${WORKDIR}/git" # NOTE: the following library dependencies are unknown, ignoring: curses # (this is based on recipes that have previously been built and packaged) DEPENDS = "file zlib ncurses" # NOTE: if this software is not capable of being built in a separate build directory # from the source, you should replace autotools with autotools-brokensep in the # inherit line inherit pkgconfig gettext autotools # Specify any options you want to pass to the configure script using EXTRA_OECONF: EXTRA_OECONF = "" AUTOTOOLS_AUTORECONF = "yes" do_configure(){ oe_runconf }
Look how recipetool is able to resolve dependency
To confirm that package recipe can build without any problem
bitbake nano
I hope that it is done without any problem, but you will almost face those problems First problem is falling fetch process
I overcome this problem by make cloning manually
cd ~/YOCTO/poky/build/downloads/git2 mkdir git.savannah.gnu.org.git.nano.git. git clone https://git.savannah.gnu.org/git/nano.git nano
After this step, when making bitbake for package recipe again, you may face problem
I will move to the path that is expected to find configuration folder
To generate a configuration script (in the same path you get, like the previous image, run this command)
./autogen.sh
After those steps, when run this command expected to work smoothly without problems
bitbkae nano
-
Integrate rpi to be able to make screen mirroring from MAC devices
To create package recipe will use recipetool
cd ~/YOCTO/poky/meta-ivi mkdir recipes-info cd recipes-info mkdir rpiplay cd rpiplay recipetool create -o rpi-play.bb https://github.com/FD-/RPiPlay.git
content of rpi-play.bb
# Recipe created by recipetool # This is the basis of a recipe and may need further editing in order to be fully functional. # (Feel free to remove these comments when editing.) # WARNING: the following LICENSE and LIC_FILES_CHKSUM values are best guesses - it is # your responsibility to verify that the values are complete and correct. # # The following license files were not able to be identified and are # represented as "Unknown" below, you will need to check them yourself: # LICENSE # lib/llhttp/LICENSE-MIT # lib/playfair/LICENSE.md LICENSE = "Unknown" LIC_FILES_CHKSUM = "file://LICENSE;md5=1ebbd3e34237af26da5dc08a4e440464 \ file://lib/llhttp/LICENSE-MIT;md5=f5e274d60596dd59be0a1d1b19af7978 \ file://lib/playfair/LICENSE.md;md5=c7cd308b6eee08392fda2faed557d79a" SRC_URI = "git://github.com/FD-/RPiPlay.git;protocol=https;branch=master" # Modify these as desired PV = "1.0+git${SRCPV}" SRCREV = "64d0341ed3bef098c940c9ed0675948870a271f9" S = "${WORKDIR}/git" # NOTE: the following library dependencies are unknown, ignoring: openmaxil plist-2 vchiq_arm brcmGLESv2 vcos bcm_host plist brcmEGL # (this is based on recipes that have previously been built and packaged) DEPENDS = "openssl" inherit cmake pkgconfig # Specify any options you want to pass to cmake using EXTRA_OECMAKE: EXTRA_OECMAKE = ""
will find that the recipetool makes partially resolving to dependencies DEPENDS = "openssl" but when going to repo link, will find a lot of dependencies need to resolved
First, I will confirm that these dependencies exist in any layer I have Check if I have avahi and can also confirm if you have it by run
cd ~/YOCTO/poky/ find . -name "avahi"
Check if I have plist
After confirming that I have all of those packages in any layer, I can add them to dependencies without problems
So update this variable in rpi-play.bb to be
DEPENDS = "avahi libplist openssl" -
Integrate Audio to be able to play sound
will use ALSA tool that has this Architecture
will create class recipe to install recipes needed to support audio
cd ~/YOCTO/poky/meta-ivi mkdir classes cd classes/ touch audio.bbclass
Content of audio.bbclass
IMAGE_INSTALL:append = " packagegroup-rpi-test pavucontrol pulseaudio pulseaudio-module-dbus-protocol pulseaudio-server pulseaudio-module-loopback pulseaudio-module-bluetooth-discover alsa-ucm-conf pulseaudio-module-bluetooth-policy alsa-topology-conf alsa-state alsa-lib alsa-tools pulseaudio-module-bluez5-discover libsocketcan\ pulseaudio-module-bluez5-device alsa-utils alsa-plugins rpi-play can-utils net-tools gstreamer1.0 iproute2 iputils qtbase-examples qtquickcontrols qtbase-plugins qtquickcontrols2 qtgraphicaleffects qtmultimedia qtserialbus qtquicktimeline qtvirtualkeyboard bluez5 bluez5-noinst-tools i2c-tools hostapd iptables packagegroup-tools-bluetooth gstreamer1.0-plugins-base gstreamer1.0-plugins-good "
To include those packages in final image, I need to update ivi-test-image.bb that is image recipe
# 1. include base image require recipes-sato/images/core-image-sato.bb # 2. set of local varaibles SUMMARY = "A simple IVI test image that include rpi function + helloworld package recipe" inherit audio # 3. IMAGE_INSTALL IMAGE_INSTALL:append = " worldhello openssh rpi-play nano dhcpcd net-tools" # 4. IMAGE_FEATURES # 1. install ssh # 2. allow root access through ssh # 3. access root through ssh using empty password IMAGE_FEATURES:append = " debug-tweaks ssh-server-openssh"
I will systemd as init process, so I will update DISTRO variable in local.conf
cd ~/YOCTO/poky/build/conf vi local.conf #change DISTRO variable to be infotainment DISTRO ?= "infotainment"
-
Integrate scrcpy to enable screen mirroring for Android
can reach repo Link Let's prepare package recipe
cd ~/YOCTO/poky/meta-ivi/recipes-info mkdir scrcpy cd scrcpy recipetool create -o scrcpy_1.0.bb https://github.com/Genymobile/scrcpy
In this repo, there are build instructions Link
From this repo understand that Scrcpy uses a client–server architecture.
Let's break down this Architecture
- Server (on Android phone)
A small Java .jar file called scrcpy-server runs inside your Android device.
It captures the screen and sends the encoded video stream (via ADB) back to the host (Raspberry Pi in your case).
It also receives control inputs (keyboard, mouse) from the host. - Client (on Raspberry Pi)
The compiled binary /usr/bin/scrcpy is the client application.
It starts an ADB connection, pushes the server JAR to the phone, starts it there, and then opens a video window (via SDL2).
It decodes the video stream using FFmpeg and shows the screen interactively.
Based on this Information, I need to get scrcpy-server. It exists in build instruction Guidance. as It need to be exist to complete build without any problem
cd ~/YOCTO/poky/meta-ivi/recipes-info/scrcpy mkdir files cd files wget https://github.com/Genymobile/scrcpy/releases/download/v3.3.3/scrcpy-server-v3.3.3 -O scrcpy-server.jar #remove extension .jar
Content of scrcpy_1.0.bb
SUMMARY = "Display and control Android devices" DESCRIPTION = "Scrcpy provides display and control of Android devices connected via USB or TCP/IP." HOMEPAGE = "https://github.com/Genymobile/scrcpy" LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://LICENSE;md5=798340522dc9eb3d3568e42ca2612bb0" # Sources: # - main source from GitHub # - server JAR provided manually in 'files/' folder SRC_URI = "git://github.com/Genymobile/scrcpy.git;protocol=https;branch=master \ file://scrcpy-server \ " PV = "3.3.3+git${SRCPV}" SRCREV = "e5e58b1b307d92cbe3432431a9e22cd648f8d4d1" S = "${WORKDIR}/git" DEPENDS = "ffmpeg libsdl2 libusb libdrm meson-native ninja-native" RDEPENDS:${PN} += "android-tools" inherit meson pkgconfig # Disable building the server (we provide our own) # EXTRA_OEMESON += "-Dbuild_server=false" # --- FIX: patch meson.build to skip server --- do_configure:prepend() { # comment out any "subdir('server')" line to avoid missing build file errors sed -i '/subdir.*server/d' ${S}/meson.build } do_install() { install -d ${D}${bindir} install -m 0755 ${B}/app/scrcpy ${D}${bindir}/scrcpy install -d ${D}${datadir}/scrcpy install -m 0644 ${WORKDIR}/scrcpy-server ${D}${datadir}/scrcpy/scrcpy-server } FILES:${PN} += "${datadir}/scrcpy"
Explain some points in pcakge Recipe
- Server (on Android phone)
🙌🙌Finally, to create a Linux Image Distribution
update ivi-test-image.bb
# 1. include base image ---> # 1. Poky # 2. BSP require recipes-sato/images/core-image-sato.bb # 2. set of local varaibles SUMMARY = "A simple IVI test image that include rpi function + helloworld package recipe" inherit audio # 3. IMAGE_INSTALL IMAGE_INSTALL:append = " worldhello openssh rpi-play nano scrcpy android-tools dhcpcd net-tools" # 4. IMAGE_FEATURES # 1. install ssh # 2. allow root access through ssh # 3. access root through ssh using empty password IMAGE_FEATURES:append = " debug-tweaks ssh-server-openssh"
bitbake ivi-test-image
-
-
To be able to create Raspberry Pi image and flash it on SD card need to have this script
cd ~/YOCTO/ mkdir custom_scripts cd custom_scripts touch flashing.sh
content of flashing.sh
#!/usr/bin/bash function sdcard-flashing(){ if [[ "$1" == "--help" ]]; then printf "%s\n%s\n" "1st parameter: /dev/<driver>" "2nd parameter: <image iso>" return 0 fi if (( $# < 2 )); then echo "Invalid arguments passed use --help for valid options." return 1 fi declare DRIVER=$1 declare IMAGE_PATH=$2 sudo dd if="${IMAGE_PATH}" of="${DRIVER}" status=progress return 0 } function create-rpi-image(){ if [[ "$1" == "--help" ]]; then printf "%s\n%s" "1st parameter: image-name" "RUN: wic list images" return 0 fi if (( $# < 1 )); then echo "Invalid arguments passed use --help for valid options." return 1 fi declare IMAGE_NAME=$1 wic create sdimage-raspberrypi -e ${IMAGE_NAME} return 0 }
need to source this script to be loaded when any terminal open
nano ~/.bashrc # at the end of file, add those lines if [ -f "${HOME}/Hazem_Course/YOCTO/custom_scripts/flashing.sh" ]; then source "${HOME}/Hazem_Course/YOCTO/custom_scripts/flashing.sh" fi
-
Let's create image
to do this will create folder as any time will create image should exist in this path and run command
cd cd ~/YOCTO/poky mkdir rasp-images cd rasp-images create-rpi-image ivi-test-image
will get log like this and inform you image created
-
📥Load SD card with image
To avoid any problem, please confirm that SD card formatted (writing zero values)
Plug SD card into laptop
run this command to know user SD card name to write image for it (in my case SD card read as sdb)
lsblk
Then write image to your sd card
then unplug SD card and insert it into Raspberry pi
-
make SSH for your target machine
Confirm that your raspberry pi Ethernet pluged (your laptop and raspberry pi should conencted with wired ethernet in same network)
I need to see network configurationifconfig
will see something like this
As, I infrom we use wired so will focus with enp7s0 as I have IP = 192.168.1.8
so will try to see IP that has same subnet 192.168.1.0/24
nmap -sn 192.168.1.0/24
and will get something like this
will try to SSH to your target machine (will try IP you get)
ssh root@192.168.1.3
until get something like
🚩🚩👀👀Note at this point Screen may not work right
-
🖥️Make Screen run without any problem
to make screen work without problems as I use 7 inch LCD Display-C
will SSH your board again then do
cd nano /boot/config.txt ## add those lines # Enable VC4 Graphics (FKMS, stable with non-standard screens) dtoverlay=vc4-fkms-v3d # USB / HDMI tweaks max_usb_current=1 config_hdmi_boost=7 hdmi_force_hotplug=1 # Custom resolution for 7" LCD hdmi_group=2 hdmi_mode=87 hdmi_cvt=1024 600 60 6 0 0 0 hdmi_drive=1 # Display tweaks display_rotate=0 disable_overscan=0 max_framebuffers=2
press Ctrl + o then Enter then Ctrl + x
then make board reboot
reboot
after reboot will get screen view
-
🔊Test audio
In this step, I will test the audio to see if will work without any problem (I connect my headset to Raspberry Pi through audio jack 3.5mm I will hear from it)
I will run this cmd to list all sound playback hardware devices that ALSA (Advanced Linux Sound Architecture) can see
apaly -l
and will get this
this may be because output audio disabled , so confirm if this root cause will turn it
nano /boot/config.txt #will seach about **dtparam=audio** should confirm that uncommented and be **on** to be dtparam=audio=onpress Ctrl + o then Enter then Ctrl + x
then make reboot and run same command
apaly -l
will get
will confirm playing local sound will work without problem
aplay /usr/share/sounds/alsa/Front_Center.wav
This line will work, but you won't hear anything this may happen as when run apaly -l find in result that
HDMI- is card 0Headphone- is card 1 So, maybe default audio move to card 0
there are 2 option for fix
-
change HW card that used to play audio (Headphone)
aplay -D plughw:1,0 /usr/share/sounds/alsa/Front_Center.wav
After this will hear audio from headphone
-
set default output to be Headphone (Recommended)
nano /etc/asound.conf # add this content pcm.!default { type hw card 1 } ctl.!default { type hw card 1 }
-
ᛒ test Bluetooth and audio
In this point I will try to connect my phone to Raspberry Pi to through bluetooth and play audio from my phone and hear it from my headphone connected to Raspberry Pi
need to run this application, this will introduce Pulseaudio process run
bluetoothctl show
need to make it discoverable and don't time out
discoverable yes discoverable-timeout 0
In your phone turn on bluetooth and if connected before please make forget (unpair) to avoid any problem then connect your phone to bluetooth name raspberrypi4-64
in your target machine keep on bluetoothctl and will find logs indicate accepting authorizationto confirm that connection established right and audio will move from phone to headphone of raspberry pi in your phone when increase/decrease volume should see sound icon like this
This also logs for Raspberry Pi in terminal indicate that there is right connection
so when play any sound from your phone and find that audio not hearable from headphone side need to do following
so, currently will be able to hear audio send from phone through Headphone connected though audio jack 3.5mm
-
Test Scrcpy
To be able to make screen mirroring need to enable USB debugging mode
I do this by going to settings in my phone and go to About Phone then press multiple time on OS version until I get pop-up informing me that Debugging mode Enabled when go to setting again and scroll down will find Additional Settings enter then scroll down until find Developer Options enter then scroll down and will Find USB debugging Enable it
Connect Your phone to Raspberry pi through USB then run following command
adb- stands for Android Debug BridgeIt’s a command-line tool that lets your computer(Raspberry Pi4) communicate with Android devices
adb devices #if everything work right without problem should get #List of devices attached #get one device that connected through USB
At this point after detect run phone you should following command through your raspberry Pi not through SSH
scrcpy
After this line, screen mirroring will start for your Android device
👀👀 May face problem that mirroring is very low (notable latency), so can run next line as run screen mirroring with reduce Target Load
scrcpy --max-fps=60 --video-bit-rate=2M --max-size=1024


