<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>MISSENE</title><link href="https://apelete.missene.com/" rel="alternate"/><link href="https://apelete.missene.com/feeds/all.atom.xml" rel="self"/><id>https://apelete.missene.com/</id><updated>2026-02-03T20:27:37.607883+01:00</updated><subtitle>Software Consultancy</subtitle><entry><title>My first talk at FOSDEM 2026</title><link href="https://apelete.missene.com/my-first-talk-at-fosdem-2026.html" rel="alternate"/><published>2026-02-02T00:00:00+01:00</published><updated>2026-02-03T20:27:37.607883+01:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2026-02-02:/my-first-talk-at-fosdem-2026.html</id><summary type="html">&lt;p&gt;&lt;a class="reference external" href="https://fosdem.org/2026/"&gt;FOSDEM'26&lt;/a&gt; is my grand premiere as a speaker at the conference.&lt;/p&gt;
&lt;p&gt;I presented &amp;quot;&lt;a class="reference external" href="https://fosdem.org/2026/schedule/event/3JBD9F-pixel_on_life-support_upgrading_from_android_12_to_android_16/"&gt;Pixel on life-support, upgrading from Android 12 to
Android 16&lt;/a&gt;&amp;quot;, a talk on the relevance of custom ROMs (in 2026
still...)  and a quick recap of my journey upgrading my Pixel 4a all
the way up to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a class="reference external" href="https://fosdem.org/2026/"&gt;FOSDEM'26&lt;/a&gt; is my grand premiere as a speaker at the conference.&lt;/p&gt;
&lt;p&gt;I presented &amp;quot;&lt;a class="reference external" href="https://fosdem.org/2026/schedule/event/3JBD9F-pixel_on_life-support_upgrading_from_android_12_to_android_16/"&gt;Pixel on life-support, upgrading from Android 12 to
Android 16&lt;/a&gt;&amp;quot;, a talk on the relevance of custom ROMs (in 2026
still...)  and a quick recap of my journey upgrading my Pixel 4a all
the way up to Android 16.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="Pixel On Life Support Screenshot" src="pictures/first_talk_fosdem_26/pixel_on_life_support.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;You can &lt;a class="reference external" href="https://fosdem.org/2026/schedule/event/3JBD9F-pixel_on_life-support_upgrading_from_android_12_to_android_16/"&gt;watch the replay and download my slides&lt;/a&gt; from the event webpage.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Or get the files mirrored here for the record :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="pictures/first_talk_fosdem_26/pixel_on_life_support.webm"&gt;Video recording in WEBM format&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="pictures/first_talk_fosdem_26/pixel_on_life_support.mp4"&gt;Video recording in MP4 format&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="pictures/first_talk_fosdem_26/pixel_on_life_support.pdf"&gt;Slides in PDF format&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It was a very nice experience and even though I've been going to
FOSDEM for many years now, this time felt special and personal.&lt;/p&gt;
&lt;p&gt;Apart from my obvious involvement with the presentation, I was also
fortunate to meet with a fellow Evolution X maintainer and a few
people from the custom ROM community : &lt;a class="reference external" href="https://lineageos.org/"&gt;LineageOS&lt;/a&gt;, &lt;a class="reference external" href="https://calyxos.org/"&gt;CalyxOS&lt;/a&gt; and
&lt;a class="reference external" href="https://e.foundation/e-os/"&gt;/e/OS&lt;/a&gt; among others.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="Lineage Stickers" src="pictures/first_talk_fosdem_26/lineage_stickers.jpg" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Meeting people In-Real-Life is the main purpose of this kind of events
; the nature of free and open-source projects makes it so that people
are often contributing remotely, from different countries, in
different timezones and as their schedule allows them to.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Needless to say having the opportunity to gather and meet in person is quite an exception.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I was very pleased to meet another developer from Evolution X and we
got to spend some quality time together.&lt;/p&gt;
&lt;p&gt;Along with the people from other Android distribution projects, we
spend the week-end together during the conference at the &lt;a class="reference external" href="https://www.ulb.be/en/ulb-homepage"&gt;ULB&lt;/a&gt;,
discussing what we do and sharing some insight on things we haven't
get the chance to touch on before.&lt;/p&gt;
&lt;p&gt;I am very happy to be part of a welcoming community, and I hope this
will become the occasion for recurring reunions.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Wishing you all well on your way back home.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Until we meet again, cheers.&lt;/p&gt;
</content><category term="Hacking &amp; Tao"/><category term="FOSDEM Android"/></entry><entry><title>Android 16 QPR1 in Evolution X, FOSDEM release</title><link href="https://apelete.missene.com/android-16-qpr1-in-evolution-x-fosdem-release.html" rel="alternate"/><published>2026-01-31T00:00:00+01:00</published><updated>2026-02-01T00:07:47.669210+01:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2026-01-31:/android-16-qpr1-in-evolution-x-fosdem-release.html</id><summary type="html">&lt;p&gt;My first Android 16 QPR1 official release is finally here : introducing
Evolution X 11.5.2 !&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://apelete.missene.com/android-16-qpr1-situation-unofficial-test-builds.html"&gt;I touched on the QPR1 situation&lt;/a&gt; to explain why this first Quarterly
Platform Release took so long to be integrated in custom ROMs -
Evolution X not being at fault here - and I am pleased …&lt;/p&gt;</summary><content type="html">&lt;p&gt;My first Android 16 QPR1 official release is finally here : introducing
Evolution X 11.5.2 !&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://apelete.missene.com/android-16-qpr1-situation-unofficial-test-builds.html"&gt;I touched on the QPR1 situation&lt;/a&gt; to explain why this first Quarterly
Platform Release took so long to be integrated in custom ROMs -
Evolution X not being at fault here - and I am pleased to get it out at
long last.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;I haven't been sitting idle until now though.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Since my first Android 16 release, 11.4.1, I have been trying to
improve the performance of my devices after getting feedback from
users about lag and general UI responsiveness.&lt;/p&gt;
&lt;p&gt;The situation was serious enough to took it upon myself and search for
a solution. Thanks to fellow maintainers and fruitful discussions, I
spent some time reading code and sweeping through the changes of &lt;a class="reference external" href="https://github.com/QuinceROMs/device_oneplus_sm8150-common-1"&gt;a
QuinceROMs repository&lt;/a&gt;, the developer is providing unofficial
Evolution X builds for Snapdragon 855 SoC (SM8150 platform) and
OnePlus devices in particular, with a special focus on performance
improvements.
This is exactly what I needed, having all my Pixel devices based on
Snapdragon SoCs while being quite older and less powerful than the
SM8150.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;By filtering the git history on the changes done in the &lt;em&gt;vendor.prop&lt;/em&gt; file in the Android 16 branch, I got &lt;a class="reference external" href="https://github.com/QuinceROMs/device_oneplus_sm8150-common-1/commits/16-d/vendor.prop"&gt;a list of commits addressing performance issues&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then it was &amp;quot;just&amp;quot; a matter of :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;reading through all those changes,&lt;/li&gt;
&lt;li&gt;exercising some common sense with regard to my own issues,&lt;/li&gt;
&lt;li&gt;manually cherry-picking some of those,&lt;/li&gt;
&lt;li&gt;building and testing them to include or reject.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Simple and straightforward, right ? :-)&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;I ended up with a few commits providing significant improvements : &lt;a class="reference external" href="https://github.com/Evolution-X-Devices/device_google_sunfish/commits/bka/vendor.prop?author=apelete"&gt;check them out here&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I also kept rebasing my device tree on the work of LineageOS for
Android 16 QPR1, just to make sure I get any upstream fix and
improvement that may benefit my users.&lt;/p&gt;
&lt;p&gt;Long story short, after a few weeks of patience and multiple testing
rounds, we finally have my first official Android 16 QPR1 release :
Evolution X 11.5.2 for the Pixel 4a, Pixel 4a 5G and Pixel 5 with
decent UI responsiveness !&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://evolution-x.org/devices/sunfish"&gt;Pixel 4a releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://evolution-x.org/devices/bramble"&gt;Pixel 4a 5G releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://evolution-x.org/devices/redfin"&gt;Pixel 5 releases&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;By the way, I am currently at &lt;a class="reference external" href="https://fosdem.org/2026/"&gt;FOSDEM'26&lt;/a&gt;, where I will be presenting on &lt;a class="reference external" href="https://fosdem.org/2026/schedule/event/3JBD9F-pixel_on_life-support_upgrading_from_android_12_to_android_16/"&gt;Pixel on life-support, upgrading from Android 12 to Android 16&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;More on that topic later.&lt;/p&gt;
&lt;p&gt;In the meantime, enjoy Evolution 11.5.2 &amp;quot;FOSDEM 26&amp;quot; release and
#KeepEvolving.&lt;/p&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="FOSDEM"/></entry><entry><title>Android 16 QPR1 situation, unofficial test builds</title><link href="https://apelete.missene.com/android-16-qpr1-situation-unofficial-test-builds.html" rel="alternate"/><published>2025-12-22T00:00:00+01:00</published><updated>2025-12-29T00:02:53.044851+01:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2025-12-22:/android-16-qpr1-situation-unofficial-test-builds.html</id><summary type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2025-12-24&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Updated all Android 16 builds to include performance improvements.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;&lt;strong&gt;ORIGINAL 2025-12-22&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Android 16 release has been a peculiar one.&lt;/p&gt;
&lt;p&gt;Google usually releases the source code of the latest version of its
mobile operation system to the Android Open-Source Project (AOSP)
repositories : this process is what allows the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2025-12-24&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Updated all Android 16 builds to include performance improvements.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;&lt;strong&gt;ORIGINAL 2025-12-22&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Android 16 release has been a peculiar one.&lt;/p&gt;
&lt;p&gt;Google usually releases the source code of the latest version of its
mobile operation system to the Android Open-Source Project (AOSP)
repositories : this process is what allows the custom ROM community to
provide alternative builds, with modification and enhancements not
found in Google's stock offering.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Things have been changing lately.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Following the release of Android 16, we no longer have the source code
being developed in the open, directly in AOSP, as progress is being
made.&lt;/p&gt;
&lt;p&gt;Instead progress is now made in private, and dropped to AOSP
afterwards ; &lt;a class="reference external" href="https://www.androidauthority.com/google-android-development-aosp-3538503/"&gt;check out this article to learn more on the subject&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As a consequence of this change, Android 16 QPR1 source code has not
been available in AOSP repositories until November 2025, while it was
officially present within the Pixel 10 lineup, Google's own commercial
line of smartphones, at the end of August 2025.&lt;/p&gt;
&lt;p&gt;Three months after release, the big Material 3 Expressive redesign of
Android 16 could not be included in custom ROM builds as the sources
of this major overhaul has been kept private that long.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Was the delay related to some engineering difficulty to release the open-source components ?&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Will this kind of situation become a trend, a new norm resulting from
Android Open-Source Project new development and release model ?&lt;/p&gt;
&lt;p&gt;Only time will tell, and we are starting to see some improvements to
make up for the delay.&lt;/p&gt;
&lt;p&gt;First of all, Android 16 QPR1 sources are now being integrated into
Evolution X code base.&lt;/p&gt;
&lt;p&gt;Given the substantial impact, I am still preparing for its official
release : to make sure issues are identified and fixed, I am now
providing test builds for users willing to help with this process :&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pixel 4a Android 16 QPR1 test build&lt;/strong&gt; :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/16/test/EvolutionX-16.0-20251224-sunfish-11.5.1-Unofficial.zip"&gt;Evolution X 11.5.1 for Pixel 4a test build&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/16/test/boot-sunfish-11.5.1.img"&gt;Corresponding Pixel 4a boot image&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Pixel 4a 5G Android 16 QPR1 test build&lt;/strong&gt; :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/test/EvolutionX-16.0-20251224-bramble-11.5-Unofficial.zip"&gt;Evolution X 11.5 for Pixel 4a 5G test build&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/test/boot-bramble-11.5.img"&gt;Corresponding Pixel 4a 5G boot sector image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/test/dtbo-bramble-11.5.img"&gt;Corresponding Pixel 4a 5G dtbo sector image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/test/vendor_boot-bramble-11.5.img"&gt;Corresponding Pixel 4a 5G vendor_boot sector image&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Pixel 5 Android 16 QPR1 test build&lt;/strong&gt; :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/test/EvolutionX-16.0-20251224-redfin-11.5-Unofficial.zip"&gt;Evolution X 11.5 for Pixel 5 test build&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/test/boot-redfin-11.5.img"&gt;Corresponding Pixel 5 boot sector image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/test/dtbo-redfin-11.5.img"&gt;Corresponding Pixel 5 dtbo sector image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/test/vendor_boot-redfin-11.5.img"&gt;Corresponding Pixel 5 vendor_boot sector image&lt;/a&gt;,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Future unofficial builds may be delivered for testing purpqoses, join
&lt;a class="reference external" href="https://discord.gg/3qbSZHx"&gt;Evolution X official chat on Discord&lt;/a&gt; to stay in touch (in my
dedicated &lt;em&gt;&amp;quot;Google Pixel 4a, Pixel 4a 5G &amp;amp; Pixel 5&amp;quot;&lt;/em&gt; channel).&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;The other improvement is the availability of Android 16 QPR2 source code in AOSP.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This one was dropped in December, quickly following the QPR1 code drop
a month earlier ; check out &lt;a class="reference external" href="https://source.android.com/docs/whatsnew/site-updates?year=2025"&gt;AOSP release timeline&lt;/a&gt; and &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Android_version_history"&gt;Android
version history&lt;/a&gt; to learn more.&lt;/p&gt;
&lt;p&gt;Fingers crossed the outstanding QPR1 release schedule does not become
a trend.&lt;/p&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="Google Pixel 4a 5G"/><category term="Google Pixel 5"/></entry><entry><title>Official builds and OTA support</title><link href="https://apelete.missene.com/official-builds-and-ota-support.html" rel="alternate"/><published>2025-11-23T00:00:00+01:00</published><updated>2025-11-29T09:03:28.344592+01:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2025-11-23:/official-builds-and-ota-support.html</id><summary type="html">&lt;p&gt;As I recently became the &lt;a class="reference external" href="https://apelete.missene.com/joining-an-awesome-project-terrific-community.html"&gt;official maintainer at Evolution X project&lt;/a&gt;
for the Pixel 4a, 4a 5G and Pixel 5, the software updates I provide
for these devices are now built and released through the CI/CD
infrastructure of the project.&lt;/p&gt;
&lt;p&gt;Pace of the releases has slowed down recently because …&lt;/p&gt;</summary><content type="html">&lt;p&gt;As I recently became the &lt;a class="reference external" href="https://apelete.missene.com/joining-an-awesome-project-terrific-community.html"&gt;official maintainer at Evolution X project&lt;/a&gt;
for the Pixel 4a, 4a 5G and Pixel 5, the software updates I provide
for these devices are now built and released through the CI/CD
infrastructure of the project.&lt;/p&gt;
&lt;p&gt;Pace of the releases has slowed down recently because we, at Evolution
X, have been doing a major upgrade of the build and release tools.
The goal is to streamline our work as maintainers, with the added
benefit of simplifying our internal processes and making future
releases more reliable.&lt;/p&gt;
&lt;p&gt;Long story short, from now on the updates for my devices will be
available on the project website as official builds :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Pixel 4a : &lt;a class="reference external" href="https://evolution-x.org/devices/sunfish"&gt;https://evolution-x.org/devices/sunfish&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Pixel 4a 5G : &lt;a class="reference external" href="https://evolution-x.org/devices/bramble"&gt;https://evolution-x.org/devices/bramble&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Pixel 5 : &lt;a class="reference external" href="https://evolution-x.org/devices/redfin"&gt;https://evolution-x.org/devices/redfin&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At the time of this writing, for each device, you will get the
following builds :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Evolution X 10.x, starting with 10.9 (Android 15 with September
2025 security patches),&lt;/li&gt;
&lt;li&gt;Evolution X 11.x, starting with 11.4.1 (Android 16 with November
2025 security patches),&lt;/li&gt;
&lt;li&gt;each major version comes with Google Apps built-in by default, or
without any of these applications if you choose the Vanilla variant.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every official build is signed with the project keys for security
reasons ; once you are running a major version of an official release,
the following updates will be delivered through an Over-The-Air
download directly to your device.&lt;/p&gt;
&lt;p&gt;Neat, isn't it ?&lt;/p&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="Google Pixel 4a"/><category term="Google Pixel 4a 5G"/><category term="Google Pixel 5"/></entry><entry><title>Rooting Android with KernelSU</title><link href="https://apelete.missene.com/rooting-android-with-kernelsu.html" rel="alternate"/><published>2025-11-02T00:00:00+01:00</published><updated>2025-11-02T18:35:40.537977+01:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2025-11-02:/rooting-android-with-kernelsu.html</id><summary type="html">&lt;div class="section" id="what-is-rooting"&gt;
&lt;h2&gt;What is rooting ?&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Rooting_(Android)"&gt;Wikipedia definition&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&amp;quot;Rooting is the process by which users of Android devices can attain
privileged control (known as root access) over various subsystems of
the device, usually smartphones and tablets. Because Android is based
on a modified version of the Linux kernel, rooting an Android device
gives …&lt;/blockquote&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="section" id="what-is-rooting"&gt;
&lt;h2&gt;What is rooting ?&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Rooting_(Android)"&gt;Wikipedia definition&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&amp;quot;Rooting is the process by which users of Android devices can attain
privileged control (known as root access) over various subsystems of
the device, usually smartphones and tablets. Because Android is based
on a modified version of the Linux kernel, rooting an Android device
gives access to administrative (superuser) permissions similar to
those on Linux [...]&amp;quot;&lt;/blockquote&gt;
&lt;p&gt;To put it simply, one might want to do something on a device that
requires special access, like uninstalling an application that was
provided by the vendor as part of the system.&lt;/p&gt;
&lt;p&gt;As the application is considered to be part of the system, the user
needs to be able to delete the privileged files related to the
application, hence the requirement to become a &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Superuser"&gt;&amp;quot;super-user&amp;quot; in the
Unix way&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="a-case-for-the-pixel-4a"&gt;
&lt;h2&gt;A case for the Pixel 4a&lt;/h2&gt;
&lt;p&gt;On Android, there is a way to become superuser of the device at hand.&lt;/p&gt;
&lt;p&gt;And just like Linux, it is done by executing the su binary.&lt;/p&gt;
&lt;p&gt;Sounds simple and straightforward, right ?&lt;/p&gt;
&lt;p&gt;Problem is, su is never shipped by default by any smartphone
manufacturer, and for obvious reasons : privilege escalation can be a
security loophole in the wrong hands, especially with phones ; devices
which are at the same time easily misplaced and contain very personal
data nowadays.&lt;/p&gt;
&lt;p&gt;The process of gaining access to su has evolved over the years, as
security loopholes were patched and new ways were engineered, and one
of the popular method for the time being is called &lt;a class="reference external" href="https://kernelsu.org/"&gt;KernelSU&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As the name implies, it is a kernel based framework.&lt;/p&gt;
&lt;p&gt;It relies on debugging mechanisms like the &lt;a class="reference external" href="https://docs.kernel.org/trace/kprobes.html"&gt;Linux kernel probes&lt;/a&gt;
(aka. kprobes) to provide hardware breakpoints, access physical memory
or intercept any system call of any process invisibly, among other
functionalities, thanks to the capability of running in kernel mode.&lt;/p&gt;
&lt;blockquote&gt;
&amp;quot;Additionally, KernelSU provides a module system via OverlayFS, which
allows you to load your custom plugin into system.&amp;quot; &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[*]&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;It is actually through that module loading mechanism that we get
access to su, which is the primary module provided by the framework.&lt;/p&gt;
&lt;p&gt;So, how to actually install KernelSU ?&lt;/p&gt;
&lt;p&gt;As said before, this is a kernel based framework : there is no way around
rebuilding the kernel with the proper modifications to embed the
framework into it.&lt;/p&gt;
&lt;p&gt;The resulting modified Android kernel can then be delivered as a boot
sector image which needs to be flashed into the device using the
flashboot tool (one of the &lt;a class="reference external" href="https://developer.android.com/tools/releases/platform-tools"&gt;Android SDK Platform Tools&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With the su enabled kernel, it is just a matter of logging in and
calling su :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ./adb shell
sunfish:/ $ su
su
sunfish:/ #
&lt;/pre&gt;
&lt;p&gt;Notice how the prompt changed from '$' to '#', to mark the change in
user. Subtle, yet powerful.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="shortcomings-room-for-improvement"&gt;
&lt;h2&gt;Shortcomings, room for improvement&lt;/h2&gt;
&lt;p&gt;KernelSU is not without issues though.&lt;/p&gt;
&lt;p&gt;For one, it is best suited for &lt;a class="reference external" href="https://source.android.com/docs/core/architecture/kernel/generic-kernel-image"&gt;Generic Kernel Images&lt;/a&gt; (GKI for short).&lt;/p&gt;
&lt;p&gt;The GKI project is a key initiative by Google to address kernel
fragmentation in Android by unifying the core kernel across all
devices, beginning with Android 12 and devices shipping with kernel
version 5.10.&lt;/p&gt;
&lt;p&gt;Reducing the fragmentation due to vendor specific changes in the
kernel allowed both security and Android major release updates to be
rolled-out in more efficient and streamlined way, thus reducing the
overall fragmentation across Android releases (ie. it is now easier
for hardware vendors to improve their software update support thanks
to the GKI project).&lt;/p&gt;
&lt;p&gt;Helas, the Pixel 4a shipped with Android 10 and kernel 4.14 : GKI was
still in the works at the time.&lt;/p&gt;
&lt;p&gt;As a consequence, the latest versions of KernelSU are not compatible
with Android kernel 4.14, and I had to rely on the older &lt;a class="reference external" href="https://github.com/tiann/KernelSU/releases/tag/v0.9.5"&gt;KernelSU
v0.9.5&lt;/a&gt;, which is not ideal because a lot of fixes, new features and
improvements are not available.&lt;/p&gt;
&lt;p&gt;This situation brings me to the second shortcoming : application
developers came out with ways to detect root privileges escalation
provided by KernelSU and prevent their apps to be run in such
situations (again, obvious security concerns may justify such a move,
at the expense of the user rights to do what he needs to with the
device).&lt;/p&gt;
&lt;p&gt;One solution to that problem is called &lt;a class="reference external" href="https://kernelsu-next.github.io/webpage/"&gt;KernelSU Next&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Simply put, this new framework improves upon the former by :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;providing support for both GKI and non-GKI Android kernels,&lt;/li&gt;
&lt;li&gt;providing &lt;a class="reference external" href="https://github.com/sidex15/susfs4ksu-module"&gt;a module called SUSFS&lt;/a&gt; which goal is to hide root
escalation to userspace applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And these are only two of the benefits highlighted with regards to the
Pixel 4a case.&lt;/p&gt;
&lt;p&gt;Once again, I got my hands dirty and patched my kernel in a suitable
manner to obtain a boot sector image to be flashed into the device ;
the installation process remains the same once you are familiar with
the ways of KernelSU.&lt;/p&gt;
&lt;p&gt;Going forward, it might be interesting to provide those modified boot
sector images for my Evolution X users who need root access on their
phones.&lt;/p&gt;
&lt;p&gt;For now, if you are interested in this experiment, you can download
below :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;my &lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/kernelsu/kernelsu-boot.img"&gt;kernelSU boot image for the Pixel 4a&lt;/a&gt;, and&lt;/li&gt;
&lt;li&gt;my &lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/kernelsu/kernelsu-next-boot.img"&gt;kernelSU Next + SUSFS patches boot image&lt;/a&gt; for the Pixel 4a.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is additional work on top of providing security and major release
updates, so it will depend on community demand ; as is the case with
community driven projects.&lt;/p&gt;
&lt;p&gt;That is the way :-).&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-1" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-1"&gt;[*]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a class="reference external" href="https://kernelsu.org/guide/what-is-kernelsu.html"&gt;https://kernelsu.org/guide/what-is-kernelsu.html&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="Linux kernel"/></entry><entry><title>Joining an awesome project, terrific community</title><link href="https://apelete.missene.com/joining-an-awesome-project-terrific-community.html" rel="alternate"/><published>2025-10-12T00:00:00+02:00</published><updated>2025-10-12T17:26:59.929575+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2025-10-12:/joining-an-awesome-project-terrific-community.html</id><summary type="html">&lt;p&gt;If you followed my recent posts, you know I have been interesting by
Android custom ROMs lately.&lt;/p&gt;
&lt;p&gt;Not only as a user, effectively modifying my main daily phone to run
Android 16 (it was released six years ago and abandoned on Android
12), but also as an Android apprentice developer …&lt;/p&gt;</summary><content type="html">&lt;p&gt;If you followed my recent posts, you know I have been interesting by
Android custom ROMs lately.&lt;/p&gt;
&lt;p&gt;Not only as a user, effectively modifying my main daily phone to run
Android 16 (it was released six years ago and abandoned on Android
12), but also as an Android apprentice developer learning how to build
and modify the system to keep targeted devices up-to-date with the
&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Android_(operating_system)#Development"&gt;latest AOSP release&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Scratching that itch, I built and publicly released multiple versions
of Android for the Google Pixel 4a, 4a 5G and Pixel 5, using
&lt;a class="reference external" href="https://evolution-x.org"&gt;Evolution X&lt;/a&gt; (here is &lt;a class="reference external" href="https://apelete.missene.com/pixel-5-sweet-16.html"&gt;a summary of my latest releases&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Long story short, after supporting those devices on my spare time just
for fun and learning from the community along the way for the past few
months, I recently joined the project as an official maintainer.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="Evolution X maintainers roster" src="pictures/joining_awesome_project/evolution_x_maintainers_roster.jpg" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="what-it-means-to-be-official-maintainer"&gt;
&lt;h2&gt;What it means to be official maintainer&lt;/h2&gt;
&lt;p&gt;So, what does it change ?&lt;/p&gt;
&lt;p&gt;Not much to tell the truth, but the differences are impactful.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;As a maintainer for the project, I am expected to keep the source
code of my devices up-to-date (as long as technically possible) and
suitable to be built on its &lt;a class="reference external" href="https://en.wikipedia.org/wiki/CI/CD"&gt;CI/CD infrastructure&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;As a benefit of building on Evolution X servers, my releases will
now be officially signed and can be pushed to devices as
&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Over-the-air_update#Smartphones"&gt;Over-The-Air updates&lt;/a&gt;, bypassing the need for a computer to do a
manual update each time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A huge leap in both developer and user experience obviously.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-path-moving-forward"&gt;
&lt;h2&gt;The path moving forward&lt;/h2&gt;
&lt;p&gt;So, what now ?&lt;/p&gt;
&lt;p&gt;More of the same, basically.&lt;/p&gt;
&lt;p&gt;My intent is to keep releasing updates as regularly as possible, and
use the newly gained communication channels with other maintainers to
stay informed of changes ahead of time and help fixing bugs.&lt;/p&gt;
&lt;p&gt;Here goes hoping I'll still find some spare time to continue
supporting my devices, keeping the process fun and improving by
learning from the community.&lt;/p&gt;
&lt;p&gt;Search for &amp;quot;Pixel 4a&amp;quot;, &amp;quot;Pixel 4a 5G&amp;quot; or &amp;quot;Pixel 5&amp;quot; among &lt;a class="reference external" href="https://evolution-x.org/devices"&gt;Evolution X
supported devices list&lt;/a&gt; to get my official releases.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/></entry><entry><title>It's been a long time coming</title><link href="https://apelete.missene.com/its-been-a-long-time-coming.html" rel="alternate"/><published>2025-09-29T00:00:00+02:00</published><updated>2025-09-29T19:36:33.094223+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2025-09-29:/its-been-a-long-time-coming.html</id><summary type="html">&lt;p&gt;I posted &amp;quot;&lt;a class="reference external" href="https://apelete.missene.com/pixel-5-sweet-16.html"&gt;Pixel 5, Sweet 16&lt;/a&gt;&amp;quot; a few days ago to announce the release of
Android 16 by way of my custom ROM of choice, Evolution X.&lt;/p&gt;
&lt;p&gt;It may have gone unnoticed, but there was no such release for Pixel 4a
at the time.&lt;/p&gt;
&lt;p&gt;Even though I was able to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I posted &amp;quot;&lt;a class="reference external" href="https://apelete.missene.com/pixel-5-sweet-16.html"&gt;Pixel 5, Sweet 16&lt;/a&gt;&amp;quot; a few days ago to announce the release of
Android 16 by way of my custom ROM of choice, Evolution X.&lt;/p&gt;
&lt;p&gt;It may have gone unnoticed, but there was no such release for Pixel 4a
at the time.&lt;/p&gt;
&lt;p&gt;Even though I was able to make some adaptations and build an image for
the device, flashing the image and trying to boot it resulted into
infinite loops of boot process (aka. boot-loop), only halted by
automatic restarts.&lt;/p&gt;
&lt;p&gt;Knowing that LineageOS sources for Android 16 (on which Evolution X is
based) haven't been released yet, this kind of issue was to be
expected at some point : by trying to do some adaptations ahead of
time, I am inevitably facing some early barriers to make things work.&lt;/p&gt;
&lt;p&gt;What were those issues, you may ask : some I knew from experience, and
others I was introduced to. Let's go over both.&lt;/p&gt;
&lt;div class="section" id="the-devil-i-know"&gt;
&lt;h2&gt;The devil I know&lt;/h2&gt;
&lt;p&gt;First was some Framework Compatibility Matrix issues : I wrote about
those in an &lt;a class="reference external" href="https://apelete.missene.com/whats-up-with-evolution-x-108.html"&gt;article detailing this trouble during 10.8 release&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then was a Linux kernel compilation breakage for which I had to
backport the fix.
The culprit here is '&lt;em&gt;struct sched_param&lt;/em&gt;', a well known type in POSIX
APIs exposed by the kernel for userspace applications.&lt;/p&gt;
&lt;p&gt;Problem is this particular type is also defined by glibc, so any
attempt to build some code that includes a compilation unit with that
type from both glibc and the kernel will result in&lt;/p&gt;
&lt;pre class="literal-block"&gt;
error: redefinition of ‘struct sched_param’
&lt;/pre&gt;
&lt;p&gt;Again, the issue is known at this point in time so &lt;a class="reference external" href="https://github.com/apelete/android_kernel_google_msm-4.14/commit/1cf522edbe21b861c0c2e9cafb868e9257fca031"&gt;I ported a
work-around from the Linux kernel community to fix it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Apart from these minor hiccups, I also faced tricky new ones.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-devil-i-don-t"&gt;
&lt;h2&gt;The devil I don't&lt;/h2&gt;
&lt;p&gt;As said in introduction, the image I obtained after solving some build
errors was boot-looping.&lt;/p&gt;
&lt;p&gt;Little did I know about the importance of Security-Enhanced Linux
(SELinux in short) in the Android kernel boot process before getting
to this point.&lt;/p&gt;
&lt;p&gt;SELinux is a framework in the kernel that allows enforcing access
control security policies for hardware and software components on the
system.&lt;/p&gt;
&lt;p&gt;It basically says if a component is allowed to function or run on the
system, and to which extent it can do so.&lt;/p&gt;
&lt;p&gt;For instance the camera service may be allowed to run while being
restricted from accessing properties from the display, which may have an
impact for that service to change display calibration when taking
pictures or video.
Some other sensors may also not be permitted to create specific
specific file types (eg. socket or fifo), thus preventing access to
certain modes of operation.&lt;/p&gt;
&lt;p&gt;Simply put, SELinux not only has an invisible impact on user
experience but it can also hinder the boot process if the combination
of those policies result in an incoherent state for the device to
function properly.&lt;/p&gt;
&lt;p&gt;Not having a complete picture of all services and policies that need
to be set, I guess that was the case I fell into due to some major
changes introduced with Android 16 ; it is a major release after all.&lt;/p&gt;
&lt;p&gt;If you are curious about the fixes I had to apply to make it work,
take a look at some of &lt;a class="reference external" href="https://github.com/apelete/android_device_google_sunfish/compare/lineage-22.2...LineageOS%3Aandroid_device_google_sunfish%3Alineage-22.2"&gt;the SELinux changes in my GitHub repository&lt;/a&gt;.
If you want to know more about SELinux, Lineage has a nice &amp;quot;&lt;a class="reference external" href="https://lineageos.org/engineering/HowTo-SELinux/"&gt;Working
with SELinux on Android&lt;/a&gt;&amp;quot; article on their blog.&lt;/p&gt;
&lt;p&gt;Last but not least, was an ABI breakage uncovered once SELinux
policies were better suited for the device at hand.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
out/soong/.intermediates/vendor/google/sunfish/libsecureuisvc_jni/android_arm64_armv8-a_shared/libsecureuisvc_jni.so: error: Unresolved symbol: _ZTVN7android21SurfaceComposerClient11TransactionE
out/soong/.intermediates/vendor/google/sunfish/libsecureuisvc_jni/android_arm64_armv8-a_shared/libsecureuisvc_jni.so: note:
out/soong/.intermediates/vendor/google/sunfish/libsecureuisvc_jni/android_arm64_armv8-a_shared/libsecureuisvc_jni.so: note: Some dependencies might be changed, thus the symbol(s) above cannot be resolved.
out/soong/.intermediates/vendor/google/sunfish/libsecureuisvc_jni/android_arm64_armv8-a_shared/libsecureuisvc_jni.so: note: Please re-build the prebuilt file: &amp;quot;out/soong/.intermediates/vendor/google/sunfish/libsecureuisvc_jni/android_arm64_armv8-a_shared/libsecureuisvc_jni.so&amp;quot;.
&lt;/pre&gt;
&lt;p&gt;I was faced with a new compilation error while building some obscure
library that was now being pulled into the system : I infer it was a
dependency that was not added until this stage, due to prior
roadblocks.&lt;/p&gt;
&lt;p&gt;The library in question was part of the Wi-Fi Direct (aka. WFD)
service, and it was missing some even more obscure symbol that was
obviously needed now.
Problem is the library was shipped as a binary module, with no source
code to be found.&lt;/p&gt;
&lt;p&gt;Luckily for me it was being loaded into another component written in
C++ for which sources were readily available.
The idea to work around the problem was to write a weak definition of
the missing symbol, hoping that it will not result in a severe
drawback at runtime.&lt;/p&gt;
&lt;p&gt;After all, WFD service is one of the cornerstone of features like
peer-to-peer wireless sharing and screen casting in Android ; here
goes hoping those features will not be hindered on the Pixel 4a
because of this.&lt;/p&gt;
&lt;p&gt;Once again, you can have a look at &lt;a class="reference external" href="https://github.com/apelete/frameworks_native/commit/af9056ed70e957ec4a7fd64033f6bf365f8ca3da"&gt;the weak implementation for
the missing symbol here&lt;/a&gt;.
And here are interesting reads on &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Wi-Fi_Direct"&gt;Wi-Fi Direct protocol&lt;/a&gt; and &lt;a class="reference external" href="https://www.androidcentral.com/what-wi-fi-direct-and-how-do-you-use-it"&gt;some
of its use in Android&lt;/a&gt;.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="Evolution X 11.2 on Pixel 4a" src="pictures/been_a_long_time_coming/android_16_pixel_4a.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;All is said and done, but it would not have been possible without some
specific Android debugging tools.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="better-to-have-it-and-not-need-it"&gt;
&lt;h2&gt;Better to have it and not need it&lt;/h2&gt;
&lt;p&gt;My Pixel 4a is a finished commercial product, not an engineering
sample or development board : having a kernel that is not booting in
that case can be difficult to resolve.&lt;/p&gt;
&lt;p&gt;Android comes with useful tools for this kind of situation, and two of
them I happily abused was Android Debug Bridge (ADB) and logcat.&lt;/p&gt;
&lt;p&gt;For future reference here are a useful &amp;quot;&lt;a class="reference external" href="https://lineageos.org/engineering/HowTo-Debugging/"&gt;Android debugging crash
course&lt;/a&gt;&amp;quot; and an overview of &amp;quot;&lt;a class="reference external" href="https://www.xda-developers.com/how-to-take-logs-android/"&gt;how to take logs on Android&lt;/a&gt;&amp;quot;.&lt;/p&gt;
&lt;p&gt;ADB is a client-server application allowing the user to connect to a
device and fetch/push data from/to it.
In a production environment (once the phone leaves the factory) the
server is disabled for obvious security reasons, but to work on a
custom ROM one need to enable it to replace the stock operating system
in the first place.&lt;/p&gt;
&lt;p&gt;Logcat is the equivalent of Linux syslog, granting access to
aggregated system logs with some filtering capabilities to display
information related to a chosen process (eg. filtering all SELinux
logs without having the noise from other processes in between).&lt;/p&gt;
&lt;p&gt;As a consequence, to work on the all the issues described before, I
built an engineering image with the debugging tools I needed for the
task at hand, with ADB server running during the boot process to
have an early entry point into the system.&lt;/p&gt;
&lt;p&gt;From that point on, it was a matter of reading kernel and system logs
to find some clues, with patience being a key for success :-).&lt;/p&gt;
&lt;/div&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="Google Pixel 4a"/></entry><entry><title>Pixel 5, Sweet 16</title><link href="https://apelete.missene.com/pixel-5-sweet-16.html" rel="alternate"/><published>2025-09-20T00:00:00+02:00</published><updated>2025-11-13T14:41:54.156459+01:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2025-09-20:/pixel-5-sweet-16.html</id><summary type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2025-11-13&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Updated all Android 16 builds to Evolution X 11.4.&lt;/p&gt;
&lt;p&gt;These are stopgap Unofficial builds to mitigate the delay due to the
ongoing rework of Evolution X Official build infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2025-09-27&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Added links to Evolution X 11 builds, Android 16 update, for the Pixel
4a. At long …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2025-11-13&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Updated all Android 16 builds to Evolution X 11.4.&lt;/p&gt;
&lt;p&gt;These are stopgap Unofficial builds to mitigate the delay due to the
ongoing rework of Evolution X Official build infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2025-09-27&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Added links to Evolution X 11 builds, Android 16 update, for the Pixel
4a. At long last.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;Third time's the charm, or so it goes.&lt;/p&gt;
&lt;p&gt;My previous two attempts to provide an alternative Android
distribution (aka &amp;quot;custom ROM&amp;quot;) for the Google Pixel 4a and 4a 5G were
very successful already, and I am going at it again with the Pixel 5
this time.&lt;/p&gt;
&lt;p&gt;Is this the result of plain luck or strictly accumulated know-how ?&lt;/p&gt;
&lt;p&gt;Maybe a bit of both, given that the &lt;a class="reference external" href="https://evolution-x.org/"&gt;Evolution X&lt;/a&gt; custom ROM I am
adapting for these devices is relying on &lt;a class="reference external" href="https://en.wikipedia.org/wiki/LineageOS"&gt;LineageOS&lt;/a&gt;, which provides
a rock solid foundation for this kind of work.&lt;/p&gt;
&lt;p&gt;Note that the Lineage project has not officially released their
sources for Android 16 yet, at the time of this writing, so I had to
do some preemptive hacking and debugging work to make it all run.&lt;/p&gt;
&lt;p&gt;So, here we are again, you will find below the Evolution X 11 images for
the Pixel 4a 5G and Pixel 5 based on Android 16.&lt;/p&gt;
&lt;p&gt;And I have also built Android 15 based Evolution X for the Pixel 5 for
good measure, just in case you need it ; check out my previous
articles on &lt;a class="reference external" href="https://apelete.missene.com/android-15-on-pixel-4a-with-evolution-x.html"&gt;Evolution X for the Pixel 4a&lt;/a&gt; and the one &lt;a class="reference external" href="https://apelete.missene.com/pixel-4a-5g-a-new-device-in-our-custom-android-roster.html"&gt;adding the
Pixel 4a 5G to the roster&lt;/a&gt; if you want the previous releases for
these devices.&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="13%" /&gt;
&lt;col width="23%" /&gt;
&lt;col width="32%" /&gt;
&lt;col width="32%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;&amp;nbsp;&lt;/th&gt;
&lt;th class="head"&gt;Pixel 4a (Sunfish)&lt;/th&gt;
&lt;th class="head"&gt;Pixel 4a 5G (Bramble)&lt;/th&gt;
&lt;th class="head"&gt;Pixel 5 (Redfin)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;&lt;dl class="first last docutils"&gt;
&lt;dt&gt;Evolution X 10.x&lt;/dt&gt;
&lt;dd&gt;(Android 15)&lt;/dd&gt;
&lt;/dl&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://apelete.missene.com/android-15-on-pixel-4a-with-evolution-x.html"&gt;For Sunfish images,
refer to previous post.&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://apelete.missene.com/pixel-4a-5g-a-new-device-in-our-custom-android-roster.html"&gt;For Bramble images,
or tips on how to flash
multiple boot sector
images, refer to previous
post.&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/15/EvolutionX-15.0-20250918-redfin-10.9-Unofficial.zip"&gt;Redfin Standard image&lt;/a&gt; &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/15/boot-redfin-10.9.img"&gt;Redfin 10.x boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/15/dtbo-redfin-10.9.img"&gt;Redfin 10.x dtbo sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/15/vendor_boot-redfin-10.9.img"&gt;Redfin 10.x vendor_boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/15/EvolutionX-15.0-20250918-redfin-10.9-Vanilla-Unofficial.zip"&gt;Redfin Vanilla image&lt;/a&gt; &lt;a class="footnote-reference" href="#footnote-2" id="footnote-reference-2"&gt;[2]&lt;/a&gt;&lt;/p&gt;
&lt;ul class="last simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/15/boot-redfin-10.9-Vanilla.img"&gt;Redfin 10.x V. boot sector image&lt;/a&gt; &lt;a class="footnote-reference" href="#footnote-3" id="footnote-reference-3"&gt;[3]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/15/dtbo-redfin-10.9-Vanilla.img"&gt;Redfin 10.x V. dtbo sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/15/vendor_boot-redfin-10.9-Vanilla.img"&gt;Redfin 10.x V. vendor_boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;dl class="first last docutils"&gt;
&lt;dt&gt;Evolution X 11.x&lt;/dt&gt;
&lt;dd&gt;(Android 16)&lt;/dd&gt;
&lt;/dl&gt;
&lt;/td&gt;
&lt;td&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/16/EvolutionX-16.0-20251112-sunfish-11.4-Unofficial.zip"&gt;Sunfish Standard image&lt;/a&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/16/boot-sunfish-11.4.img"&gt;Sunfish 11.x boot image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/16/EvolutionX-16.0-20251112-sunfish-11.4-Vanilla-Unofficial.zip"&gt;Sunfish Vanilla image&lt;/a&gt;&lt;/p&gt;
&lt;ul class="last simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/16/boot-sunfish-11.4-Vanilla.img"&gt;Sunfish 11.x V. boot image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/EvolutionX-16.0-20251112-bramble-11.4-Unofficial.zip"&gt;Bramble Standard image&lt;/a&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/boot-bramble-11.4.img"&gt;Bramble 11.x boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/dtbo-bramble-11.4.img"&gt;Bramble 11.x dtbo sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/vendor_boot-bramble-11.4.img"&gt;Bramble 11.x vendor_boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/EvolutionX-16.0-20251112-bramble-11.4-Vanilla-Unofficial.zip"&gt;Bramble Vanilla image&lt;/a&gt;&lt;/p&gt;
&lt;ul class="last simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/boot-bramble-11.4-Vanilla.img"&gt;Bramble 11.x V. boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/dtbo-bramble-11.4-Vanilla.img"&gt;Bramble 11.x V. dtbo sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/16/vendor_boot-bramble-11.4-Vanilla.img"&gt;Bramble 11.x V. vendor_boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/EvolutionX-16.0-20251112-redfin-11.4-Unofficial.zip"&gt;Redfin 11.x Standard image&lt;/a&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/boot-redfin-11.4.img"&gt;Redfin 11.x boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/dtbo-redfin-11.4.img"&gt;Redfin 11.x dtbo sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/vendor_boot-redfin-11.4.img"&gt;Redfin 11.x vendor_boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/EvolutionX-16.0-20251112-redfin-11.4-Vanilla-Unofficial.zip"&gt;Redfin 11.x Vanilla image&lt;/a&gt;&lt;/p&gt;
&lt;ul class="last simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/boot-redfin-11.4-Vanilla.img"&gt;Redfin 11.x V. boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/dtbo-redfin-11.4-Vanilla.img"&gt;Redfin 11.x V. dtbo sector image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/redfin/16/vendor_boot-redfin-11.4-Vanilla.img"&gt;Redfin 11.x V. vendor_boot sector image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-1" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;quot;Standard&amp;quot; image includes Google Apps&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;quot;Vanilla&amp;quot; image does not include Google Apps&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-3" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;quot;V.&amp;quot; stands for Vanilla for sake of consiveness&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As always, feel free to peek at &lt;a class="reference external" href="https://github.com/apelete"&gt;my GitHub for sources&lt;/a&gt;.&lt;/p&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="Google Pixel 4a"/><category term="Google Pixel 4a 5G"/><category term="Google Pixel 5"/></entry><entry><title>Pixel 4a 5G, a new device in our custom Android roster</title><link href="https://apelete.missene.com/pixel-4a-5g-a-new-device-in-our-custom-android-roster.html" rel="alternate"/><published>2025-09-08T00:00:00+02:00</published><updated>2025-09-08T16:58:15.298971+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2025-09-08:/pixel-4a-5g-a-new-device-in-our-custom-android-roster.html</id><summary type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2025-09-08&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just updated both &lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/EvolutionX-15.0-20250908-bramble-10.9-Unofficial.zip"&gt;Evolution X 10.9 with Google Apps&lt;/a&gt; and &lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/EvolutionX-15.0-20250908-bramble-10.9-Vanilla-Unofficial.zip"&gt;Evolution
X 10.9 Vanilla&lt;/a&gt; (version without any Google Apps) images with a build
including September 2025 security patches.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;&lt;strong&gt;ORIGINAL 2025-09-08&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It was bound to happen.&lt;/p&gt;
&lt;p&gt;Spending time keeping my trusty old Pixel 4a updated with the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2025-09-08&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just updated both &lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/EvolutionX-15.0-20250908-bramble-10.9-Unofficial.zip"&gt;Evolution X 10.9 with Google Apps&lt;/a&gt; and &lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/EvolutionX-15.0-20250908-bramble-10.9-Vanilla-Unofficial.zip"&gt;Evolution
X 10.9 Vanilla&lt;/a&gt; (version without any Google Apps) images with a build
including September 2025 security patches.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;&lt;strong&gt;ORIGINAL 2025-09-08&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It was bound to happen.&lt;/p&gt;
&lt;p&gt;Spending time keeping my trusty old Pixel 4a updated with the latest
Android releases, including monthly security patches, got me hooked
with the process.&lt;/p&gt;
&lt;p&gt;I recently acquired the next device in the &amp;quot;Pixel A series&amp;quot;, namely
the Pixel 4a 5G, just for the fun of providing the same support to a
device that is no longer maintained by Google since Android 14.&lt;/p&gt;
&lt;p&gt;Learning with the regular 4a proved to be insightful, and building
Android 15 for the Pixel 4a 5G was a more familiar process.&lt;/p&gt;
&lt;p&gt;Changes in the filesystem partitioning result in a slightly different
flashing procedure, keep reading on if you want to know how to install
the build on your device, but for those who just want the files here
they are:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/EvolutionX-15.0-20250908-bramble-10.9-Unofficial.zip"&gt;Evolution X 10.9 with Google Apps&lt;/a&gt; included and its recovery
images:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/boot-bramble-10.9.img"&gt;regular boot sector image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/dtbo-bramble-10.9.img"&gt;regular dtbo sector image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/vendor_boot-bramble-10.9.img"&gt;regular vendor_boot sector image&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/EvolutionX-15.0-20250908-bramble-10.9-Vanilla-Unofficial.zip"&gt;Evolution X 10.9 Vanilla&lt;/a&gt;, without any Google Apps, and its
associated recovery images:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/boot-bramble-10.9-Vanilla.img"&gt;vanilla boot sector image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/dtbo-bramble-10.9-Vanilla.img"&gt;vanilla dtbo sector image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/bramble/15/vendor_boot-bramble-10.9-Vanilla.img"&gt;vanilla vendor_boot sector image&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;As previously mentioned, the partitioning of the storage space is
slightly different this time around: we have separate sectors to flash
in order to modify the boot process and allow the installation of our
custom Android distribution.&lt;/p&gt;
&lt;p&gt;We will focus on the part where we replace the bootloader with our
custom recovery bootloader: for a complete tutorial on how to unlock
the device and get to the point described below, check my article
on how to install &lt;a class="reference external" href="https://apelete.missene.com/evolution-x-on-the-google-pixel-3a.html"&gt;Evolution X on the Google Pixel 3a&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To replace the original bootloader with a custom recovery one, follow
these steps:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ./fastboot flash boot &amp;lt;path_to_boot_sector_image&amp;gt;
Sending 'boot_b' (98304 KB)                        OKAY [  2.270s]
Writing 'boot_b'                                   OKAY [  0.562s]
Finished. Total time: 3.197s

$ ./fastboot flash dtbo &amp;lt;path_to_dtbo_sector_image&amp;gt;
Sending 'dtbo_b' (16384 KB)                        OKAY [  0.470s]
Writing 'dtbo_b'                                   OKAY [  0.216s]
Finished. Total time: 1.055s

$ ./fastboot flash vendor_boot &amp;lt;path_to_vendor_boot_secor_image&amp;gt;
Sending 'vendor_boot_b' (98304 KB)                 OKAY [  2.270s]
Writing 'vendor_boot_b'                            OKAY [  0.555s]
Finished. Total time: 3.195s
&lt;/pre&gt;
&lt;p&gt;Now reboot into Recovery Mode to install the Evolution X image.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="Evolution X 10.8 Updater" src="pictures/evolution_x_pixel4a5g/evolution_x_updater.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Happy daily driving :)&lt;/p&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="Google Pixel 4a 5G"/></entry><entry><title>What's up with Evolution X 10.8</title><link href="https://apelete.missene.com/whats-up-with-evolution-x-108.html" rel="alternate"/><published>2025-08-26T00:00:00+02:00</published><updated>2025-09-07T22:27:18.348623+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2025-08-26:/whats-up-with-evolution-x-108.html</id><summary type="html">&lt;p&gt;This entry is not a change log listing new features, but rather an
overview of the changes I faced while building the &amp;quot;August 25 security
patches&amp;quot; release of Evolution X.&lt;/p&gt;
&lt;p&gt;Sorry for the &amp;quot;somewhat click bait&amp;quot; title :).&lt;/p&gt;
&lt;p&gt;This time around, &lt;a class="reference external" href="https://apelete.missene.com/android-15-on-pixel-4a-with-evolution-x.html"&gt;updating the Pixel 4a to Evolution X 10.8&lt;/a&gt; a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This entry is not a change log listing new features, but rather an
overview of the changes I faced while building the &amp;quot;August 25 security
patches&amp;quot; release of Evolution X.&lt;/p&gt;
&lt;p&gt;Sorry for the &amp;quot;somewhat click bait&amp;quot; title :).&lt;/p&gt;
&lt;p&gt;This time around, &lt;a class="reference external" href="https://apelete.missene.com/android-15-on-pixel-4a-with-evolution-x.html"&gt;updating the Pixel 4a to Evolution X 10.8&lt;/a&gt; a mere
two weeks after getting the sources from LineageOS, I discovered
something called Framework Compatibility Matrix (FCM).&lt;/p&gt;
&lt;p&gt;The Android Framework Compatibility Matrix (FCM) is an XML file that
specifies the requirements the Android framework has for the device it
runs on, defining what hardware abstraction layer (HAL) interfaces,
kernel configurations, security policies, and other system components
must be present and at what versions.&lt;/p&gt;
&lt;p&gt;It is a key component of the Vendor Interface (VINTF) framework, which
ensures compatibility between the Android framework and vendor
implementations.&lt;/p&gt;
&lt;p&gt;The FCM is used to enforce requirements at build time, runtime, and
during Vendor Test Suite (VTS) testing.&lt;/p&gt;
&lt;p&gt;It defines the minimum and maximum version ranges for HALs, kernel
configurations, security policies (sepolicy), and other system
components that the framework expects to be available on the device.&lt;/p&gt;
&lt;p&gt;For instance, a framework compatibility matrix might require a specific
version of the camera HAL or a particular kernel configuration.&lt;/p&gt;
&lt;p&gt;This might sounds very abstract and the reason is that FCM were
introduced to define the requirements the Android framework has, to
conform with vendor implementations, thus ensuring compatibility
across different devices and Android releases.&lt;/p&gt;
&lt;p&gt;For further details on the topic, refer to the &lt;a class="reference external" href="https://source.android.com/docs/core/architecture/vintf"&gt;Vendor Interface
documentation&lt;/a&gt; and specifically the &lt;a class="reference external" href="https://source.android.com/docs/core/architecture/vintf/comp-matrices"&gt;Framework Compatibility Matrix
documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To get into the weeds of the subject, here is the kind of output one
gets when the FCM requirements are no longer in line with the Pixel
4a device manifests and corresponding device compatibility matrices:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
The following HALs in device manifest are not declared in FCM &amp;lt;= level 5:
  android.hardware.audio.effect&amp;#64;7.0::IEffectsFactory/default
  android.hardware.audio&amp;#64;7.0::IDevicesFactory/default
  android.hardware.boot.IBootControl/default (&amp;#64;1)
  android.hardware.camera.provider.ICameraProvider/internal/0 (&amp;#64;1)
  android.hardware.contexthub.IContextHub/default (&amp;#64;3)
  android.hardware.drm.IDrmFactory/clearkey (&amp;#64;1)
  android.hardware.drm.IDrmFactory/widevine (&amp;#64;1)
  android.hardware.identity.IIdentityCredentialStore/default (&amp;#64;4)
  android.hardware.input.processor.IInputProcessor/default (&amp;#64;1)
  android.hardware.memtrack.IMemtrack/default (&amp;#64;1)
  android.hardware.nfc.INfc/default (&amp;#64;1)
  android.hardware.power.IPower/default (&amp;#64;5)
  android.hardware.thermal.IThermal/default (&amp;#64;2)
  android.hardware.usb.IUsb/default (&amp;#64;1)
  android.hardware.vibrator.IVibrator/default (&amp;#64;2)
  android.hardware.wifi.IWifi/default (&amp;#64;2)
  android.hardware.wifi.hostapd.IHostapd/default (&amp;#64;2)
  android.hardware.wifi.supplicant.ISupplicant/default (&amp;#64;3)
  vendor.lineage.livedisplay.IPictureAdjustment/default (&amp;#64;1)
INCOMPATIBLE

2025-08-21 22:24:45 - check_target_files_vintf.py - INFO    : stderr: ERROR: files are incompatible: The following instances are in the device manifest but not specified in framework compatibility matrix:
    vendor.lineage.livedisplay.IPictureAdjustment/default (&amp;#64;1)
Suggested fix:
1. Update deprecated HALs to the latest version.
2. Check for any typos in device manifest or framework compatibility matrices with FCM version &amp;gt;= 5.
3. For new platform HALs, add them to any framework compatibility matrix with FCM version &amp;gt;= 5 where applicable.
4. For device-specific HALs, add to DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE or DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE.: Success

[...]
RuntimeError: VINTF compatibility check failed
&lt;/pre&gt;
&lt;p&gt;Note that all changes to solve these issues were done in the repo
project &amp;quot;&lt;em&gt;vendor/lineage/&lt;/em&gt;&amp;quot; within the file
&amp;quot;&lt;em&gt;config/device_framework_matrix.xml&lt;/em&gt;&amp;quot;.&lt;/p&gt;
&lt;p&gt;So I had to amend the aforementioned FCM XML file to add new
requirements that were introduced in the framework when I was building
Android 15 with August 2025 security patches for the Pixel 4a.&lt;/p&gt;
&lt;p&gt;The tricky part was to get the XML syntax right, since many revisions
of the compatibility matrix format were introduced alongside each AOSP
release throughout the years.&lt;/p&gt;
&lt;p&gt;Long story short, I finally came up with the new requirements written
with proper syntax : you can have a look at my change to &lt;a class="reference external" href="https://github.com/Evolution-X/vendor_evolution/commit/807f0e447628d0e46ed7ce73df9d4b2b05165f85"&gt;update FCM
requirements introduced during Evolution X 10.8 rebase&lt;/a&gt; on my Github
repository.&lt;/p&gt;
&lt;p&gt;In the process, I also stumbled upon a tool that might ease the XML
file generation if this occurs again, check it out:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/Thereache/Generate-framework-compatibility-matrix-from-fqnames#"&gt;How to generate FCM from fqnames&lt;/a&gt;&lt;/p&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="Google Pixel 4a"/></entry><entry><title>Android 15 on Pixel 4a with Evolution X</title><link href="https://apelete.missene.com/android-15-on-pixel-4a-with-evolution-x.html" rel="alternate"/><published>2025-06-25T00:00:00+02:00</published><updated>2025-09-08T12:54:57.539815+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2025-06-25:/android-15-on-pixel-4a-with-evolution-x.html</id><summary type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2025-09-08&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just updated both &lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/15/EvolutionX-15.0-20250907-sunfish-10.9-Unofficial.zip"&gt;Evolution X 10.9 with Google Apps&lt;/a&gt; and &lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/15/EvolutionX-15.0-20250907-sunfish-10.9-Vanilla-Unofficial.zip"&gt;Evolution
X 10.9 Vanilla&lt;/a&gt; (version without any Google Apps) images with a build
including September 2025 security patches.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;&lt;strong&gt;ORIGINAL 2025-06-25&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Following the walkthrough on how to run &lt;a class="reference external" href="https://apelete.missene.com/evolution-x-on-the-google-pixel-3a.html"&gt;Evolution X on the Google
Pixel 3a&lt;/a&gt;, I have …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2025-09-08&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just updated both &lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/15/EvolutionX-15.0-20250907-sunfish-10.9-Unofficial.zip"&gt;Evolution X 10.9 with Google Apps&lt;/a&gt; and &lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/15/EvolutionX-15.0-20250907-sunfish-10.9-Vanilla-Unofficial.zip"&gt;Evolution
X 10.9 Vanilla&lt;/a&gt; (version without any Google Apps) images with a build
including September 2025 security patches.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;&lt;strong&gt;ORIGINAL 2025-06-25&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Following the walkthrough on how to run &lt;a class="reference external" href="https://apelete.missene.com/evolution-x-on-the-google-pixel-3a.html"&gt;Evolution X on the Google
Pixel 3a&lt;/a&gt;, I have been using the Android custom rom distribution on a
Samsung Galaxy S10 as my daily driver.&lt;/p&gt;
&lt;p&gt;I got curious about the process of building it myself, and decided to
take the experiment with a &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Pixel_4a"&gt;Pixel 4a&lt;/a&gt;, for which Google ended
official software support in 2023 with Android 13.&lt;/p&gt;
&lt;p&gt;Evolution X provided an alternative with a custom update to Android 14
for the device, so I picked it up from there and built an update to
Android 15, with some help from the community and following the
&lt;a class="reference external" href="https://wiki.evolution-x.org/"&gt;project documentation&lt;/a&gt; (yes, they do have useful documentation !).&lt;/p&gt;
&lt;p&gt;Long story short, the experiment was successful and I came up with two
versions of Evolution X, allowing one to update the Pixel 4a to
Android 15:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/15/EvolutionX-15.0-20250907-sunfish-10.9-Unofficial.zip"&gt;Evolution X 10.9 with Google Apps&lt;/a&gt; included and its &lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/15/boot-sunfish-10.9.img"&gt;recovery
image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/15/EvolutionX-15.0-20250907-sunfish-10.9-Vanilla-Unofficial.zip"&gt;Evolution X 10.9 Vanilla&lt;/a&gt;, without any Google Apps, and its
&lt;a class="reference external" href="https://apelete.missene.com/files/sunfish/15/boot-sunfish-10.9-Vanilla.img"&gt;associated recovery image&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="Evolution X Android 15 version" src="./pictures/android_15_pixel4a/evolutionx_android_version.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you have a Pixel 4a lying around and dare to try, you can follow
&lt;a class="reference external" href="https://apelete.missene.com/evolution-x-on-the-google-pixel-3a.html"&gt;the guide I wrote on how to flash those images&lt;/a&gt; on your phone.&lt;/p&gt;
&lt;p&gt;If you are interested about what happened behind the scenes, take a
look at the sources on my github account instead:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/apelete/android_device_google_sunfish"&gt;device tree sources&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/apelete/proprietary_vendor_google_sunfish"&gt;vendor tree sources&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/apelete/sunfish_local_manifests"&gt;one manifest to rule them all&lt;/a&gt; ;-).&lt;/li&gt;
&lt;/ul&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="Google Pixel 4a"/></entry><entry><title>Evolution X on the Google Pixel 3a</title><link href="https://apelete.missene.com/evolution-x-on-the-google-pixel-3a.html" rel="alternate"/><published>2024-08-24T00:00:00+02:00</published><updated>2024-08-23T23:28:51.818100+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2024-08-24:/evolution-x-on-the-google-pixel-3a.html</id><summary type="html">&lt;p&gt;My main issue with Android has always been the very short support we
get from manufacturers once we buy their phones; things have been
improving lately but I still own a perfectly fine Pixel 3a for which
Google has stopped providing any updates since 2022.&lt;/p&gt;
&lt;p&gt;So, I decided to install …&lt;/p&gt;</summary><content type="html">&lt;p&gt;My main issue with Android has always been the very short support we
get from manufacturers once we buy their phones; things have been
improving lately but I still own a perfectly fine Pixel 3a for which
Google has stopped providing any updates since 2022.&lt;/p&gt;
&lt;p&gt;So, I decided to install a community maintained distribution (aka
&amp;quot;custom rom&amp;quot;) to extend software support myself with a more up-to-date
version of the Pixel 3a OS: I have chosen &lt;a class="reference external" href="https://wiki.evolution-x.org/"&gt;Evolution X&lt;/a&gt; for this
purpose, which should allow me to run Android 14 instead of Google's
last Android 12 update.&lt;/p&gt;
&lt;p&gt;First let's download the following &lt;a class="reference external" href="https://sourceforge.net/projects/evolution-x/files/sargo/14/"&gt;Evolution X Android 14 files for
Pixel 3a&lt;/a&gt;:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;custom &lt;a class="reference external" href="https://sourceforge.net/projects/evolution-x/files/sargo/14/boot/boot.img/download"&gt;boot recovery image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://sourceforge.net/projects/evolution-x/files/sargo/14/EvolutionX-14.0-20240818-sargo-v9.3-Official.zip/download"&gt;Evolution X 14 v9.3 image&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/Evolution-XYZ/vendor_certification/raw/udc/PifPrebuilt/PifPrebuilt.apk"&gt;Google Play Integrity fix APK&lt;/a&gt; from the &lt;a class="reference external" href="https://xdaforums.com/t/rom-14-0-0_r53-official-evolution-x-9-2-07-28-2024.4683738/"&gt;project page on XDA Forum&lt;/a&gt;,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will also need the &lt;a class="reference external" href="https://developer.android.com/tools/releases/platform-tools"&gt;Android SDK Platform Tools&lt;/a&gt; to connect and
transfer the previous files to the device:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://dl.google.com/android/repository/platform-tools-latest-linux.zip"&gt;SDK Platform Tools for Linux&lt;/a&gt;,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Flashing the vendor official OS voids the device warranty&lt;/strong&gt; (when
warranty is still applicable, which is not the case here since the
phone is no longer supported), and the bootloader is locked by default
to prevent such practice.&lt;/p&gt;
&lt;p&gt;To unlock the bootloader:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;dl class="first docutils"&gt;
&lt;dt&gt;Enable developer options:&lt;/dt&gt;
&lt;dd&gt;go to Settings &amp;gt; About phone &amp;gt; Build number, and tap it 7
times to enable &amp;quot;Developer mode&amp;quot;,&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="first docutils"&gt;
&lt;dt&gt;Enable OEM unlocking:&lt;/dt&gt;
&lt;dd&gt;in Developer options, toggle the switch next to “OEM
unlocking” to enable it; also toggle the switch next to &amp;quot;USB
debugging&amp;quot; to enable sending files via USB later,&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="first docutils"&gt;
&lt;dt&gt;Boot into Bootloader Mode:&lt;/dt&gt;
&lt;dd&gt;with your phone connected to your PC via USB, boot your Pixel
3a into bootloader mode by pressing and holding the &amp;quot;Power&amp;quot;
button and the &amp;quot;Volume down&amp;quot; button simultaneously,&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;li&gt;&lt;dl class="first docutils"&gt;
&lt;dt&gt;Run fastboot commands:&lt;/dt&gt;
&lt;dd&gt;extract the Android SDK Platform Tools archive previously
downloaded, open a command prompt, navigate to the directory
and run the fastboot command to unlock your bootloader as
follows:&lt;/dd&gt;
&lt;/dl&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="literal-block"&gt;
$ cd platform-tools/
$ sudo ./fastboot flashing unlock
OKAY [  0.089s]
Finished. Total time: 0.089s
&lt;/pre&gt;
&lt;p&gt;Note that the command is run with sudo to get the rights to
communicate with the device; if everything goes well you should get
the OKAY output meaning we can now proceed with replacing the original
bootloader with a custom recovery bootloader:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo ./fastboot flash boot ~/boot.img
Sending 'boot_b' (65536 KB)                        OKAY [  1.530s]
Writing 'boot_b'                                   OKAY [  0.342s]
Finished. Total time: 2.185s
&lt;/pre&gt;
&lt;p&gt;Reboot into Recovery Mode to install the Evolution X image:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Press any &amp;quot;Volume&amp;quot; button to scroll until &amp;quot;Recovery Mode&amp;quot; is shown
next to &amp;quot;Power&amp;quot; button,&lt;/li&gt;
&lt;li&gt;Press &amp;quot;Power&amp;quot; button to select and wait for device to reboot,&lt;/li&gt;
&lt;li&gt;In recovery mode, using the &amp;quot;Volume&amp;quot; buttons, navigate to &amp;quot;Factory
reset&amp;quot; and select with &amp;quot;Power&amp;quot; button,&lt;/li&gt;
&lt;li&gt;Navigate back and select &amp;quot;Apply update&amp;quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From the command prompt, sideload the image:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo ./adb sideload ~/EvolutionX-14.0-20240818-sargo-v9.3-Official.zip
serving: 'EvolutionX-14.0-20240818-sargo-v9.3-Official.zip'  (~100%)
Total xfer: 2.00x
&lt;/pre&gt;
&lt;p&gt;With the transfer complete, navigate back and select &amp;quot;Reboot system
now&amp;quot; to boot into your new system ; first boot will be longer than
usual.&lt;/p&gt;
&lt;p&gt;After initial setup, the familiar Pixel homescreen should show up.&lt;/p&gt;
&lt;img alt="Evolution X V9.3 Updater" src="pictures/evolution_x_pixel3a/evolution_x_updater.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Congratulations, the Google Pixel 3a is now running Android 14 !&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Optional:&lt;/strong&gt; At this point, you can connect the device to your
computer, transfer the &lt;a class="reference external" href="https://github.com/Evolution-XYZ/vendor_certification/raw/udc/PifPrebuilt/PifPrebuilt.apk"&gt;Google Play Integrity fix APK&lt;/a&gt; and install it
from &amp;quot;Files&amp;quot; application.&lt;/p&gt;
&lt;p&gt;Afterwards, &lt;a class="reference external" href="https://developer.android.com/google/play/integrity"&gt;Play Integrity API&lt;/a&gt; checks should pass, in case you want
to use Google Pay or banking apps on your device.&lt;/p&gt;
</content><category term="Hacking &amp; Tao"/><category term="Android"/><category term="Google Pixel 3a"/></entry><entry><title>Create a Steam Deck Debian rescue image</title><link href="https://apelete.missene.com/create-a-steam-deck-debian-rescue-image.html" rel="alternate"/><published>2024-08-18T00:00:00+02:00</published><updated>2024-08-19T18:12:21.875583+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2024-08-18:/create-a-steam-deck-debian-rescue-image.html</id><summary type="html">&lt;p&gt;Following the &lt;a class="reference external" href="https://apelete.missene.com/running-debian-on-steam-deck-from-sd-card.html"&gt;installation of Debian 12 on the Steam Deck&lt;/a&gt;, we are
now going to backup the SD Card content into a rescue image : the idea
is to be able to recover and duplicate the whole running system easily
without having to re-install again if needs be.&lt;/p&gt;
&lt;p&gt;There are at …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Following the &lt;a class="reference external" href="https://apelete.missene.com/running-debian-on-steam-deck-from-sd-card.html"&gt;installation of Debian 12 on the Steam Deck&lt;/a&gt;, we are
now going to backup the SD Card content into a rescue image : the idea
is to be able to recover and duplicate the whole running system easily
without having to re-install again if needs be.&lt;/p&gt;
&lt;p&gt;There are at least two ways to achieve this :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;using the dd tool from the command line,&lt;/li&gt;
&lt;li&gt;relying on gnome-disk-utility GUI to create a disk image.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="section" id="using-dd-command-line-tool-to-create-a-disk-image"&gt;
&lt;h2&gt;Using dd command line tool to create a disk image&lt;/h2&gt;
&lt;p&gt;Since I am making an image of an SD Card mounted at /dev/mmcblk0 and
wish to create an image named &amp;quot;steamdeck-debian-repair-20240818.iso&amp;quot;,
the command line I am using for this purpose is the following:&lt;/p&gt;
&lt;pre class="code shell literal-block"&gt;
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./steamdeck-debian-repair-20240818.iso&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1M&lt;span class="w"&gt;
&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sync
&lt;/pre&gt;
&lt;p&gt;Executing this as root with sudo allows us to read from mmcblk0 device
indeed and create an iso from its content.&lt;/p&gt;
&lt;p&gt;Conversely, restoring such an image shall be a matter of:&lt;/p&gt;
&lt;pre class="code shell literal-block"&gt;
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dd&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./steamdeck-debian-repair-20240818.iso&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1M&lt;span class="w"&gt;
&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sync
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="using-gnome-disk-utility-gui-to-create-a-disk-image"&gt;
&lt;h2&gt;Using gnome-disk-utility GUI to create a disk image&lt;/h2&gt;
&lt;p&gt;As an alternative, if you are using the GNOME desktop environment, you
may as well rely on gnome-disk-utility (simply called &amp;quot;Disks&amp;quot; on the
desktop) to the same extent:&lt;/p&gt;
&lt;img alt="Creating Steam Deck rescue image - Create disk image" src="./pictures/steamdeck_rescue_image/gnome-disk-utility-create-image.png" /&gt;
&lt;p&gt;Choose &amp;quot;Create Disk Image&amp;quot; from the menu...&lt;/p&gt;
&lt;img alt="Creating Steam Deck rescue image - Provide image name" src="./pictures/steamdeck_rescue_image/gnome-disk-utility-image-name.png" /&gt;
&lt;p&gt;Name your image accordingly...&lt;/p&gt;
&lt;img alt="Creating Steam Deck rescue image - Status progress" src="./pictures/steamdeck_rescue_image/gnome-disk-utility-progress.png" /&gt;
&lt;p&gt;And wait for the process to complete.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Once you have your image file, restoring from it is as simple as
double-clicking on the file to launch &amp;quot;Disks&amp;quot;:&lt;/p&gt;
&lt;img alt="Creating Steam Deck rescue image - Restoring disk image" src="./pictures/steamdeck_rescue_image/gnome-disk-utility-restore.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In my experience, creating a backup image of the 64GB SD Card takes
around 12 minutes with both methods.&lt;/p&gt;
&lt;p&gt;You now have the choice either way.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Hacking &amp; Tao"/><category term="Steam Deck"/></entry><entry><title>Running Debian on Steam Deck from SD Card</title><link href="https://apelete.missene.com/running-debian-on-steam-deck-from-sd-card.html" rel="alternate"/><published>2024-08-15T00:00:00+02:00</published><updated>2024-08-19T18:12:29.575573+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2024-08-15:/running-debian-on-steam-deck-from-sd-card.html</id><summary type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2024-08-18&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I recently posted about &lt;a class="reference external" href="https://apelete.missene.com/create-a-steam-deck-debian-rescue-image.html"&gt;creating a rescue image of my Debian
installation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That post was driven by issues where it would no longer be possible to
boot into the Linux install on the SD Card, due to the bootloader
entry mysteriously disappearing.&lt;/p&gt;
&lt;p&gt;It looks like the UEFI specs …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;UPDATE 2024-08-18&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I recently posted about &lt;a class="reference external" href="https://apelete.missene.com/create-a-steam-deck-debian-rescue-image.html"&gt;creating a rescue image of my Debian
installation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That post was driven by issues where it would no longer be possible to
boot into the Linux install on the SD Card, due to the bootloader
entry mysteriously disappearing.&lt;/p&gt;
&lt;p&gt;It looks like the UEFI specs may actually be suggesting that the Debian
system shall provide a FAT32 system partition for the UEFI to be able
to achieve boot process related operations:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
13.3 File System Format
The file system supported by the Extensible Firmware Interface is based on the FAT file system.
[...]
EFI encompasses the use of FAT32 for a system partition, and FAT12 or FAT16 for removable media.

13.3.1 System Partition
A System Partition is a partition in the conventional sense of a partition on a legacy system.
For a hard disk, a partition is a contiguous grouping of sectors on the disk where the starting
sector and size are defined by the Master Boot Record (MBR), which resides on LBA 0 (i.e., the
first sector of the hard disk) ( LBA 0 Format ), or the GUID Partition Table (GPT), which resides
on logical block 1 (the second sector of the hard disk) ( GPT overview ).

13.3.1.1 File System Format
The first block (sector) of a partition contains a data structure called the BIOS Parameter Block
(BPB) that defines the type and location of FAT file system on the drive.
[...]
The first block (sector) also contains code that will be executed as part of the boot process on a
legacy system.
&lt;/pre&gt;
&lt;p&gt;That is, &lt;a class="reference external" href="https://uefi.org/specs/UEFI/2.10_A/13_Protocols_Media_Access.html#file-system-format"&gt;if I understand the UEFI Specification correctly&lt;/a&gt;...&lt;/p&gt;
&lt;p&gt;As a consequence, I have since revised the partition table of my
Debian installation to provide said FAT32 partition at the beginning
of the SD Card drive:&lt;/p&gt;
&lt;img alt="Debian 12 installation - Overview 4" src="./pictures/debian_on_steamdeck/32_partman_choose_partition_1.png" /&gt;
&lt;p&gt;As you can see above, it now shows:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;148.9 MB for the UEFI FAT32 system partition,&lt;/li&gt;
&lt;li&gt;537.9 MB for our UEFI bootloader,&lt;/li&gt;
&lt;li&gt;20.9 GB for the root system,&lt;/li&gt;
&lt;li&gt;1 GB for the swap,&lt;/li&gt;
&lt;li&gt;39.9 GB for the home partition.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;&lt;strong&gt;ORIGINAL 2024-08-15&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It's been a while since I posted online, and I recently bought a Steam
Deck so now might be the time to document and share what I am having
fun with once again :-).&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Steam_Deck"&gt;Steam Deck&lt;/a&gt; is basically a handheld gaming PC running
&lt;a class="reference external" href="https://www.steamdeck.com/en/software"&gt;SteamOS&lt;/a&gt;, a dedicated &lt;a class="reference external" href="https://store.steampowered.com/steamos"&gt;Linux distribution developed by Valve&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Valve's current operating system, &lt;a class="reference external" href="https://en.wikipedia.org/wiki/SteamOS"&gt;SteamOS version 3&lt;/a&gt;, is based on
Arch Linux but the distribution was initially built from Debian.&lt;/p&gt;
&lt;p&gt;It currently runs great and serves a purpose ; would it still be
possible to run Debian on the Steam Deck though ?&lt;/p&gt;
&lt;p&gt;To find out, I tried installing and running Debian 12 from the
device's SD Card as a dual boot solution to avoid messing the internal
SSD.&lt;/p&gt;
&lt;p&gt;Here is my setup:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Steam Deck,&lt;/li&gt;
&lt;li&gt;External keyboard &amp;amp; mouse,&lt;/li&gt;
&lt;li&gt;External display,&lt;/li&gt;
&lt;li&gt;USB flash drive with Debian image,&lt;/li&gt;
&lt;li&gt;Dock to connect peripherals to the device,&lt;/li&gt;
&lt;li&gt;64 GB SD Card installation medium.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I am not going through where to find those accessories, or even how to
create a bootable Debian USB flash drive : there are plenty of
resources on the internet to learn about those, let's jump right in.&lt;/p&gt;
&lt;p&gt;To boot from the flash drive, hold Volume Down while pressing Power
button on the Deck and release after you hear the chime : that should
bring you to the boot menu where you can select your flash drive.&lt;/p&gt;
&lt;p&gt;First screens of the Debian installer are trivial : language, keyboard
selection and keymap.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Select a language" src="./pictures/debian_on_steamdeck/01_localechooser_languagelist_0.png" /&gt;
&lt;img alt="Debian 12 installation - Select your location" src="./pictures/debian_on_steamdeck/02_localechooser_shortlist_0.png" /&gt;
&lt;img alt="Debian 12 installation - Configure the keyboard" src="./pictures/debian_on_steamdeck/03_keyboard-configuration_xkb-keymap_0.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then comes the network interface chooser:&lt;/p&gt;
&lt;img alt="Debian 12 installation - Primary network interface" src="./pictures/debian_on_steamdeck/04_netcfg_choose_interface_0.png" /&gt;
&lt;p&gt;Here I select the ethernet interface available on the dock, as it does
not need any specific driver to work during installation.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Hostname" src="./pictures/debian_on_steamdeck/05_netcfg_get_hostname_0.png" /&gt;
&lt;p&gt;Then the hostname ;-).&lt;/p&gt;
&lt;img alt="Debian 12 installation - Domain name" src="./pictures/debian_on_steamdeck/06_netcfg_get_domain_0.png" /&gt;
&lt;p&gt;Domain name is left by default.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I skipped creating a root user, choosing for the primary user to
elevate his rights through sudo instead:&lt;/p&gt;
&lt;img alt="Debian 12 installation - Full name for the new user" src="./pictures/debian_on_steamdeck/07_passwd_user-fullname_0.png" /&gt;
&lt;img alt="Debian 12 installation - Username for your account" src="./pictures/debian_on_steamdeck/08_passwd_username_0.png" /&gt;
&lt;img alt="Debian 12 installation - Choose a password for the new user" src="./pictures/debian_on_steamdeck/09_passwd_user-password_0.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Now comes the tricky part: partitioning to boot Debian from SD while
keeping SteamOS on the SSD.&lt;/p&gt;
&lt;p&gt;The Steam Deck boots from UEFI, as a consequence we will also need a
partition to install a compatible bootloader.&lt;/p&gt;
&lt;p&gt;I am starting with an empty card and choosing manual partitioning:&lt;/p&gt;
&lt;img alt="Debian 12 installation - Overview 1" src="./pictures/debian_on_steamdeck/10_partman_choose_partition_3.png" /&gt;
&lt;p&gt;As you can see from the overview, I have access to multiple drives:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;the 64 GB SD Card I want to install Debian onto (mmcblk0),&lt;/li&gt;
&lt;li&gt;the Deck's 256 GB internal SSD we do not want to mess with (nvme0n1),&lt;/li&gt;
&lt;li&gt;the 2 GB flash drive I am running the Debian installer from (sda).&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="Debian 12 installation - Create new partition table" src="./pictures/debian_on_steamdeck/11_partman-partitioning_confirm_new_label_0.png" /&gt;
&lt;p&gt;Select the SD Card free space to create a new partition table.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Overview 2" src="./pictures/debian_on_steamdeck/12_partman_choose_partition_1.png" /&gt;
&lt;img alt="Debian 12 installation - How to use this free space 1" src="./pictures/debian_on_steamdeck/13_partman_free_space_0.png" /&gt;
&lt;p&gt;Select again to create a new partition.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Location for the new partition" src="./pictures/debian_on_steamdeck/14_partman-partitioning_new_partition_place_0.png" /&gt;
&lt;p&gt;The new partition shall start at the beginning of the available space.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Type for the new partition" src="./pictures/debian_on_steamdeck/15_partman-partitioning_new_partition_type_0.png" /&gt;
&lt;p&gt;And we want it to be a logical partition as you can only have a
limited number of primary partitions.&lt;/p&gt;
&lt;img alt="Debian 12 installation - New partition size" src="./pictures/debian_on_steamdeck/16_partman-partitioning_new_partition_size_2.png" /&gt;
&lt;p&gt;Let's make this partition 64 MB...&lt;/p&gt;
&lt;img alt="Debian 12 installation - How to use this partition" src="./pictures/debian_on_steamdeck/17_partman-target_choose_method_0.png" /&gt;
&lt;p&gt;...as we want to use it for the EFI compatible bootloader.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Partition settings" src="./pictures/debian_on_steamdeck/18_partman_active_partition_4.png" /&gt;
&lt;p&gt;Make sure the partition is bootable ; the bootable flag should be on
by default though.&lt;/p&gt;
&lt;img alt="Debian 12 installation - How to use this free space 2" src="./pictures/debian_on_steamdeck/19_partman_free_space_2.png" /&gt;
&lt;p&gt;After setting up the first partition, select the remaining free space
and let the installer automatically partition it.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Partitioning scheme" src="./pictures/debian_on_steamdeck/20_partman-auto_choose_recipe_0.png" /&gt;
&lt;p&gt;We want root, home and swap partitions to be separate to keep things
simple yet modular enough.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Overview 3" src="./pictures/debian_on_steamdeck/21_partman_choose_partition_4.png" /&gt;
&lt;p&gt;And here we are, with our complete partitioning scheme:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;65 MB for our EFI bootloader partition,&lt;/li&gt;
&lt;li&gt;21.1 GB for the system,&lt;/li&gt;
&lt;li&gt;1 GB for the swap,&lt;/li&gt;
&lt;li&gt;40.3 GB for the home partition.&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="Debian 12 installation - Write the changes to disks" src="./pictures/debian_on_steamdeck/22_partman_confirm_0.png" /&gt;
&lt;p&gt;Confirm those changes and write this partition table to disk.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We are out of the woods, the rest is rather straightforward:&lt;/p&gt;
&lt;img alt="Debian 12 installation - Debian archive mirror country" src="./pictures/debian_on_steamdeck/23_mirror_http_countries_0.png" /&gt;
&lt;p&gt;To configure the package manager, select the country of the Debian
archive mirror you want to get software from.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Debian archive mirror" src="./pictures/debian_on_steamdeck/24_mirror_http_mirror_0.png" /&gt;
&lt;p&gt;Then the mirror itself.&lt;/p&gt;
&lt;img alt="Debian 12 installation - HTTP proxy information" src="./pictures/debian_on_steamdeck/25_mirror_http_proxy_0.png" /&gt;
&lt;p&gt;A proxy if you need one.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Configuring popularity-contest" src="./pictures/debian_on_steamdeck/26_popularity-contest_participate_0.png" /&gt;
&lt;p&gt;And here I choose to provide the distribution developers with
statistics about the packages I will be using on this system.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Software selection" src="./pictures/debian_on_steamdeck/27_tasksel_first_0.png" /&gt;
&lt;p&gt;For software selection, apart from the GNOME desktop environment and
the standard utilities I also want an SSH server to connect remotely
to the device.&lt;/p&gt;
&lt;img alt="Debian 12 installation - System clock UTC" src="./pictures/debian_on_steamdeck/28_clock-setup_utc_0.png" /&gt;
&lt;p&gt;Not sure about that one, it usually messes with the way UEFI and any
other operation system handles the system clock: I left it by default
since the OSes will be syncing the time from the network anyway.&lt;/p&gt;
&lt;img alt="Debian 12 installation - Installation complete" src="./pictures/debian_on_steamdeck/29_finish-install_reboot_in_progress_0.png" /&gt;
&lt;p&gt;Here goes nothing: now is the time to reboot into Debian :-).&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="Debian 12 installation - GRUB UEFI" src="./pictures/debian_on_steamdeck/30_grub_uefi.jpg" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;So far so good, our GRUB bootloader offers a sensible list of choices...&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="Debian 12 installation - SUCCESS" src="./pictures/debian_on_steamdeck/31_debian_on_steamdeck.jpg" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And the proof is in the pudding: here is the Debian 12 login screen,
on the Steam Deck, after a successful installation process !&lt;/p&gt;
&lt;p&gt;For future reference, I have also included below data gathered during
installation:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;complete &lt;a class="reference external" href="pictures/debian_on_steamdeck/hardware-summary"&gt;hardware summary&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;initial &lt;a class="reference external" href="pictures/debian_on_steamdeck/syslog"&gt;syslog&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="pictures/debian_on_steamdeck/Xorg.0.log"&gt;Xorg display log&lt;/a&gt; file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's all folks !&lt;/p&gt;
</content><category term="Hacking &amp; Tao"/><category term="Steam Deck"/><category term="Linux kernel"/></entry><entry><title>Linux 3.18 released, contributions of mine</title><link href="https://apelete.missene.com/linux-318-released-contributions-of-mine.html" rel="alternate"/><published>2014-12-14T00:00:00+01:00</published><updated>2024-08-20T00:01:36.124131+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-12-14:/linux-318-released-contributions-of-mine.html</id><summary type="html">&lt;p&gt;Catching up on kernel news while recovering from illness, &lt;a class="reference external" href="http://lwn.net/Articles/624979/"&gt;Linux 3.18
was released a week ago&lt;/a&gt; like clockwork. As part of this release,
there are two patches of mine inside.&lt;/p&gt;
&lt;p&gt;Those are about adding DMA support to the MMC/SD card driver of the
Ben NanoNote SoC -- namely the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Catching up on kernel news while recovering from illness, &lt;a class="reference external" href="http://lwn.net/Articles/624979/"&gt;Linux 3.18
was released a week ago&lt;/a&gt; like clockwork. As part of this release,
there are two patches of mine inside.&lt;/p&gt;
&lt;p&gt;Those are about adding DMA support to the MMC/SD card driver of the
Ben NanoNote SoC -- namely the JZ4740 SoC.&lt;/p&gt;
&lt;p&gt;Until now, the SD card driver was operating in &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Programmed_input/output"&gt;PIO mode&lt;/a&gt;: solely
relying on the CPU to transfer data between the SD card and main
memory. The goal of the patches is to allow the driver to rely on DMA
instead in order to improve performance.&lt;/p&gt;
&lt;p&gt;So I started by adding DMA support by taking advantage of the DMA
Engine driver that was already available for JZ4740.
Trying to push performance further, I then took advantage of the
asynchronous request capability of the MMC framework to prepare the
next DMA transfer request in parallel with the current ongoing
transfer.&lt;/p&gt;
&lt;p&gt;I posted a few benchmarks with the patch series to track performance
improvements. Please refer to LKML to read them (I'm not sure the text
output would be correctly formatted on this blog, and I'm being too
lazy to find out):&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://lkml.org/lkml/2014/7/21/11"&gt;https://lkml.org/lkml/2014/7/21/11&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can read from my post on LKML, there is a minor improvement in
average transfer time (going from 7 to 6 minutes to uncompress Fedora
16 ISO image) and CPU load. This is a good thing overall: considering
the limited scope of my benchmark, the improvement might be even more
noticeable while doing a bigger transfer while the CPU is under a
heavier load.&lt;/p&gt;
&lt;p&gt;Also, in hindsight, zcat was probably not a very good utility to
benchmark memory transfers. Using dd may have given more relevant
results and a better picture of the overall performance improvement
gained by using DMA instead of CPU for memory transfers.&lt;/p&gt;
&lt;p&gt;Anyway, here are links to the patches:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7ca27a6f80a4042666a28977ff8ee3aa527c6cd4"&gt;https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7ca27a6f80a4042666a28977ff8ee3aa527c6cd4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=bb2f45927f8e0d1fc0633f65cc1f17a40c80bf24"&gt;https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=bb2f45927f8e0d1fc0633f65cc1f17a40c80bf24&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And a summary of all the changes by kernelnewbies.org:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://kernelnewbies.org/Linux_3.18"&gt;http://kernelnewbies.org/Linux_3.18&lt;/a&gt;&lt;/p&gt;
</content><category term="Archives"/><category term="Ben NanoNote"/><category term="Linux kernel"/></entry><entry><title>Attending LinuxCon &amp; ELC Europe 2014</title><link href="https://apelete.missene.com/attending-linuxcon-elc-europe-2014.html" rel="alternate"/><published>2014-10-26T00:00:00+02:00</published><updated>2024-08-15T19:16:50.606838+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-10-26:/attending-linuxcon-elc-europe-2014.html</id><summary type="html">&lt;img alt="LinuxCon &amp;amp; ELCE 2014 Badge" src="./pictures/linuxcon-badge-2014.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a class="reference external" href="http://events.linuxfoundation.org/events/linuxcon-europe"&gt;LinuxCon Europe&lt;/a&gt; and &lt;a class="reference external" href="http://events.linuxfoundation.org/events/embedded-linux-conference-europe"&gt;Embedded Linux Conference Europe&lt;/a&gt; (ELCE) 2014 took
place in Dusseldorf earlier this month, from 13th to 15th of October.&lt;/p&gt;
&lt;p&gt;I was granted a scholarship from the Linux Foundation to attend the
event for the first time this year. This was unexpected I must say,
leading to last …&lt;/p&gt;</summary><content type="html">&lt;img alt="LinuxCon &amp;amp; ELCE 2014 Badge" src="./pictures/linuxcon-badge-2014.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a class="reference external" href="http://events.linuxfoundation.org/events/linuxcon-europe"&gt;LinuxCon Europe&lt;/a&gt; and &lt;a class="reference external" href="http://events.linuxfoundation.org/events/embedded-linux-conference-europe"&gt;Embedded Linux Conference Europe&lt;/a&gt; (ELCE) 2014 took
place in Dusseldorf earlier this month, from 13th to 15th of October.&lt;/p&gt;
&lt;p&gt;I was granted a scholarship from the Linux Foundation to attend the
event for the first time this year. This was unexpected I must say,
leading to last minute preparations in order to go to Dusseldorf.&lt;/p&gt;
&lt;p&gt;This being my first time attending the event, I didn't know what to
expect apart from the experience I got by going to other FOSS
conferences like &lt;a class="reference external" href="http://apelete.missene.com/openembedded-coverage-at-fosdem-2014.html"&gt;FOSDEM&lt;/a&gt; and &lt;a class="reference external" href="http://apelete.missene.com/going-to-guadec-2014.html"&gt;GUADEC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What really stood out from my point of view was the logistics around
the event, at least the visible part of it.
Once on site, at the Congress Center Düsseldorf (CCD) where it
happened, everything seemed to have been taken care of. From the
people holding the registration/reception desk all day long, to the
waitresses and waiters serving food and drinks all day long (including
proper breakfast and lunch!), to the people recording the talks and
taking pictures in every room again all day long, the organisation was
really top notch.&lt;/p&gt;
&lt;p&gt;Don't get me wrong now, the other events I experienced in the past
certainly required a lot of organising too, and they were just as much
enjoyable. In fact, it would have been difficult for me to attend
&lt;a class="reference external" href="http://events.linuxfoundation.org/events/linuxcon-europe"&gt;LinuxCon&lt;/a&gt; &amp;amp; &lt;a class="reference external" href="http://events.linuxfoundation.org/events/embedded-linux-conference-europe"&gt;ELCE&lt;/a&gt; without the scholarship given the hefty
registration fee required.&lt;/p&gt;
&lt;p&gt;Knowing that does not make the care and effort put into the
preparations of the event less commendable. Kudos to the Linux
Foundation and to all the people who were involved into the &amp;quot;behind
the scenes&amp;quot; making of these conferences !&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="Linuxcon 2014 name tag" src="./pictures/linuxcon_tag_2014.png" /&gt;
&lt;p&gt;My LinuxCon &amp;amp; ELCE name tag.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As far as the talks went, it was a thrill seeing some key FOSS
contributors on stage and actually meeting a few of them in person.&lt;/p&gt;
&lt;p&gt;I got the opportunity to meet the team behind the &lt;a class="reference external" href="http://apelete.missene.com/mips-creator-ci20.html"&gt;MIPS Creator CI20
project&lt;/a&gt;, and it was really energising discussing with them.
I also bumped into a few friends, some of them long time attendees of
this kind of events, and we hopped on the occasion to share a few
beers and good laughs together.&lt;/p&gt;
&lt;p&gt;In the end &lt;a class="reference external" href="http://events.linuxfoundation.org/events/linuxcon-europe"&gt;LinuxCon&lt;/a&gt; and &lt;a class="reference external" href="http://events.linuxfoundation.org/events/embedded-linux-conference-europe"&gt;ELCE&lt;/a&gt; were an amazing experience, adding
to the already great benefit of being part of the free and open-source
software community.&lt;/p&gt;
&lt;p&gt;Last but not least, I must take the time here to thank Marina
Zhurakhinskaya and Karen Sandler for talking me into going to
&lt;a class="reference external" href="http://events.linuxfoundation.org/events/linuxcon-europe"&gt;LinuxCon&lt;/a&gt; in the first place; it probably wouldn't have happened
without meeting both of them :-).&lt;/p&gt;
&lt;p&gt;Let's make sure we all meet soon again !&lt;/p&gt;
</content><category term="Archives"/><category term="LinuxCon"/><category term="ELCE"/><category term="Event"/></entry><entry><title>Linux 3.17 patches status</title><link href="https://apelete.missene.com/linux-317-patches-status.html" rel="alternate"/><published>2014-10-24T00:00:00+02:00</published><updated>2024-08-15T19:17:27.898792+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-10-24:/linux-317-patches-status.html</id><summary type="html">&lt;p&gt;Here is a late post on Linux 3.17 which was &lt;a class="reference external" href="https://lwn.net/Articles/615009/"&gt;pushed out a few weeks
ago&lt;/a&gt;. I planned to post a short status of my contributions, as usual,
but then I was busy making preparations to go to LinuxCon and ELC
Europe -- more on that later.&lt;/p&gt;
&lt;p&gt;Anyway, this one …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here is a late post on Linux 3.17 which was &lt;a class="reference external" href="https://lwn.net/Articles/615009/"&gt;pushed out a few weeks
ago&lt;/a&gt;. I planned to post a short status of my contributions, as usual,
but then I was busy making preparations to go to LinuxCon and ELC
Europe -- more on that later.&lt;/p&gt;
&lt;p&gt;Anyway, this one will be quick: I got a couple of fixes into 3.17 for
the JZ4740 MUSB driver.&lt;/p&gt;
&lt;p&gt;Thing is, the MUSB driver is using the generic NOP transceiver as its
PHY provider, and the transceiver was recently renamed from
usb_nop_xceiv to usb_phy_generic. The change induced a kernel panic
due to an unhandled kernel unaligned access while trying to
dereference musb-&amp;gt;xceiv-&amp;gt;io_ops in the musb_init_controller() function
in drivers/usb/musb/musb_core.c.&lt;/p&gt;
&lt;p&gt;My patches were aimed at fixing that issue, by declaring the
transceiver under its new name in the JZ4740 platform data and also
registering it in the MUSB driver to make sure the driver prints an
error message if the transceiver cannot be registered for some reason.&lt;/p&gt;
&lt;p&gt;Links to the patches:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c7fb97d65aece5b03a9209ea5a9670e952c62f34"&gt;http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c7fb97d65aece5b03a9209ea5a9670e952c62f34&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=3d75bd3d0af16c7b8dda13440202fa24769d8e17"&gt;http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=3d75bd3d0af16c7b8dda13440202fa24769d8e17&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As always, the ever useful changelog published by kernelnewbies.org:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://kernelnewbies.org/Linux_3.17"&gt;http://kernelnewbies.org/Linux_3.17&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Til next release.&lt;/p&gt;
</content><category term="Archives"/><category term="Ben NanoNote"/><category term="Linux kernel"/></entry><entry><title>MIPS Creator CI20</title><link href="https://apelete.missene.com/mips-creator-ci20.html" rel="alternate"/><published>2014-08-22T00:00:00+02:00</published><updated>2024-08-15T19:17:40.170777+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-08-22:/mips-creator-ci20.html</id><summary type="html">&lt;p&gt;I'm a happy hacker right now. Just received a &lt;a class="reference external" href="http://www.elinux.org/MIPS_Creator_CI20"&gt;MIPS Creator CI20&lt;/a&gt;
board in the mailbox a couple of days ago, thanks to &lt;a class="reference external" href="http://www.imgtec.com/"&gt;Imagination
Technologies&lt;/a&gt;.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="MIPS Creator CI20 boxed" src="./pictures/mips-creator-ci20-boxed.jpg" /&gt;
&lt;p&gt;Attention to detail: notice the many power plug adaptors for various
countries.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is a small sized development board powered by an Ingenic JZ4780
SoC …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm a happy hacker right now. Just received a &lt;a class="reference external" href="http://www.elinux.org/MIPS_Creator_CI20"&gt;MIPS Creator CI20&lt;/a&gt;
board in the mailbox a couple of days ago, thanks to &lt;a class="reference external" href="http://www.imgtec.com/"&gt;Imagination
Technologies&lt;/a&gt;.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="MIPS Creator CI20 boxed" src="./pictures/mips-creator-ci20-boxed.jpg" /&gt;
&lt;p&gt;Attention to detail: notice the many power plug adaptors for various
countries.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is a small sized development board powered by an Ingenic JZ4780
SoC with a dual core &lt;a class="reference external" href="https://en.wikipedia.org/wiki/MIPS_instruction_set"&gt;MIPS&lt;/a&gt; processor clocked at 1.2GHz.
It comes with:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;1GB of RAM + 8GB of NAND preloaded with Debian 7 &amp;quot;Wheezy&amp;quot;,&lt;/li&gt;
&lt;li&gt;1 x PowerVR SGX540 GPU,&lt;/li&gt;
&lt;li&gt;1 x SD Card port,&lt;/li&gt;
&lt;li&gt;2 x USB ports,&lt;/li&gt;
&lt;li&gt;1 x Infrared receiver,&lt;/li&gt;
&lt;li&gt;Audio Jack I/O + HDMI output,&lt;/li&gt;
&lt;li&gt;Ethernet + WiFi + Bluetooth connectivity,&lt;/li&gt;
&lt;li&gt;Expansion headers with (lo and behold) UART + JTAG support!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Full specs can be found at &lt;a class="reference external" href="http://www.elinux.org/CI20_Tech_Stuff"&gt;http://www.elinux.org/CI20_Tech_Stuff&lt;/a&gt;.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img alt="MIPS Creator CI20 unboxed" src="./pictures/mips-creator-ci20-unboxed.jpg" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/MIPS_instruction_set"&gt;MIPS&lt;/a&gt; architectures seem to have a lesser mindshare compared to
other better known ones, even though &lt;a class="reference external" href="https://en.wikipedia.org/wiki/MIPS_instruction_set"&gt;MIPS&lt;/a&gt; processors are widespread
in the embedded space. They are usually found in computer network
appliances (e.g. routers and residential gateways), digital TV
appliances (e.g. set-top boxes) and video game consoles, to name a
few.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference external" href="http://www.elinux.org/MIPS_Creator_CI20"&gt;MIPS Creator CI20&lt;/a&gt; is a project from &lt;a class="reference external" href="http://www.imgtec.com/"&gt;Imagination Technologies&lt;/a&gt;
to foster development around their architecture and raise awareness of
the products built upon it. The team behind the project released quite
a lot of documentation and source code in order to reach that goal,
making it hacker friendly.&lt;/p&gt;
&lt;p&gt;Find more about it at &lt;a class="reference external" href="http://www.elinux.org/MIPS_Creator_CI20"&gt;http://www.elinux.org/MIPS_Creator_CI20&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Does the Ingenic JZ4780 SoC rings a bell ? If you've been following
this blog, then it certainly does. It's the latest generation of the
same family of SoCs that powers the &lt;a class="reference external" href="http://apelete.missene.com/tag/ben-nanonote.html"&gt;Ben NanoNote&lt;/a&gt; and the
&lt;a class="reference external" href="http://apelete.missene.com/tag/gcw-zero.html"&gt;GCW-Zero&lt;/a&gt; -- devices I have been writing about here.&lt;/p&gt;
&lt;p&gt;Kudos to Graham Whaley and his whole team at ImgTec for building the
CI20 ! Let's see what we can squeeze out of it ;-).&lt;/p&gt;
</content><category term="Archives"/><category term="MIPS Creator CI20"/><category term="Hardware"/></entry><entry><title>Linux 3.16 released: patch inside</title><link href="https://apelete.missene.com/linux-316-released-patch-inside.html" rel="alternate"/><published>2014-08-05T00:00:00+02:00</published><updated>2024-08-15T19:17:22.078799+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-08-05:/linux-316-released-patch-inside.html</id><summary type="html">&lt;p&gt;&lt;a class="reference external" href="https://lwn.net/Articles/607527/"&gt;A new kernel release&lt;/a&gt;, and with it comes another patch of mine.&lt;/p&gt;
&lt;p&gt;A single patch this time, but this one has been in the works for a
while now. It's about providing documentation for the MUSB driver I
wrote for the Ingenic JZ4740 SoC &lt;a class="reference external" href="http://apelete.missene.com/linux-314-out-me-contributions-inside.html"&gt;which was included into Linux kernel …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a class="reference external" href="https://lwn.net/Articles/607527/"&gt;A new kernel release&lt;/a&gt;, and with it comes another patch of mine.&lt;/p&gt;
&lt;p&gt;A single patch this time, but this one has been in the works for a
while now. It's about providing documentation for the MUSB driver I
wrote for the Ingenic JZ4740 SoC &lt;a class="reference external" href="http://apelete.missene.com/linux-314-out-me-contributions-inside.html"&gt;which was included into Linux kernel
3.14&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I wrote the documentation back in February 2014 as an attempt to log
all the things I learned while writing an MUSB driver for the Ben
NanoNote.
The end result was more detailed than I initially planned, to my own
surprise, thereby I submitted it to be included in the Linux kernel
upstream -- that move was a trial balloon, truth to be told.&lt;/p&gt;
&lt;p&gt;Then came a series of unexpected events that may explain the lengthy
review process that ensued; the main one being a change of maintainer
for the kernel documentation.
Around that time Rob Landley stepped down as maintainer of the Linux
kernel documentation and handed the keys back to Randy Dunlap. As a
matter of fact, all pending patches needed to be resent:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://www.spinics.net/lists/linux-doc/msg20722.html"&gt;http://www.spinics.net/lists/linux-doc/msg20722.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The sheer size of the documentation I wrote and the Linux kernel
review and release process also contributed to the time it took for
the patch to be merged into Linux kernel 3.16 -- the rest is history,
logged into the &lt;a class="reference external" href="https://lkml.org/"&gt;Linux Kernel Mailing List&lt;/a&gt; archive ;-).&lt;/p&gt;
&lt;p&gt;Anyway, here is the documentation as I first published it on this
blog:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://apelete.missene.com/writing-an-musb-glue-layer.html"&gt;http://apelete.missene.com/writing-an-musb-glue-layer.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And the version compiled from the Linux kernel source tree, readable
online:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.kernel.org/doc/htmldocs/writing_musb_glue_layer/index.html"&gt;https://www.kernel.org/doc/htmldocs/writing_musb_glue_layer/index.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For the curious mind, a link to the patch in the kernel source tree:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=60b6dbeffb8c253d1f80527b28611e5e236dec51"&gt;http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=60b6dbeffb8c253d1f80527b28611e5e236dec51&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let's not forget the detailed changelog for Linux kernel 3.16,
courtesy of kernelnewbies.org:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://kernelnewbies.org/Linux_3.16"&gt;http://kernelnewbies.org/Linux_3.16&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Stay tuned for more !&lt;/p&gt;
</content><category term="Archives"/><category term="Ben NanoNote"/><category term="Linux kernel"/></entry><entry><title>Going to GUADEC 2014</title><link href="https://apelete.missene.com/going-to-guadec-2014.html" rel="alternate"/><published>2014-07-31T00:00:00+02:00</published><updated>2024-08-15T19:17:09.386815+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-07-31:/going-to-guadec-2014.html</id><summary type="html">&lt;img alt="GUADEC 2014 badge" src="./pictures/guadec-2014-badge-large.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The main part of the &lt;a class="reference external" href="http://www.gnome.org"&gt;GNOME&lt;/a&gt; Users And Developers European Conference
(&lt;a class="reference external" href="https://www.guadec.org"&gt;GUADEC&lt;/a&gt;) -- which took place in Strasbourg, France, this year,
actually just ended.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.guadec.org"&gt;GUADEC&lt;/a&gt; consists of two parts. The core days are when talks, keynote
presentations as well as the &lt;a class="reference external" href="http://www.gnome.org"&gt;GNOME&lt;/a&gt; Foundation Annual General
Meeting happen. The &amp;quot;Birds of a …&lt;/p&gt;</summary><content type="html">&lt;img alt="GUADEC 2014 badge" src="./pictures/guadec-2014-badge-large.png" /&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The main part of the &lt;a class="reference external" href="http://www.gnome.org"&gt;GNOME&lt;/a&gt; Users And Developers European Conference
(&lt;a class="reference external" href="https://www.guadec.org"&gt;GUADEC&lt;/a&gt;) -- which took place in Strasbourg, France, this year,
actually just ended.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.guadec.org"&gt;GUADEC&lt;/a&gt; consists of two parts. The core days are when talks, keynote
presentations as well as the &lt;a class="reference external" href="http://www.gnome.org"&gt;GNOME&lt;/a&gt; Foundation Annual General
Meeting happen. The &amp;quot;Birds of a Feather&amp;quot; (BoFs), as in saying &amp;quot;birds
of a feather flock together&amp;quot;, are working discussions about a specific
topic of interest in a group of people who share that interest.&lt;/p&gt;
&lt;p&gt;So the core days ended on July 29th. I have been a &lt;a class="reference external" href="http://www.gnome.org"&gt;GNOME&lt;/a&gt; user for
the past twelve years, using the Debian distribution for most of that
time, but this was the first time I attended the event.&lt;/p&gt;
&lt;p&gt;Just like &lt;a class="reference external" href="https://www.fosdem.org"&gt;FOSDEM&lt;/a&gt; &lt;a class="reference external" href="http://apelete.missene.com/openembedded-coverage-at-fosdem-2014.html"&gt;I attended earlier this year&lt;/a&gt;, I had a blast
going to &lt;a class="reference external" href="https://www.guadec.org"&gt;GUADEC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Meeting the people making &lt;a class="reference external" href="http://www.gnome.org"&gt;GNOME&lt;/a&gt; was an energising experience. The
community is a very welcoming and enthusiastic one. From the
organisers of the event, to the users, the developers and all the
people who manage some aspect of the community, there was a lot of
dynamism all over the place. I had many insightful conversations with
the folks there and a lot of good laughs too :-).&lt;/p&gt;
&lt;img alt="GUADEC 2014 group photo" src="./pictures/guadec-2014-group-photo.jpg" /&gt;
&lt;p&gt;Colourful GUADEC group shot. Picture by The GNOME Project, licensed
under CC-BY-3.0.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I think I really enjoy going to Free Software events in the end. It
turns out to be where the real fun lies: these moments where we share
something together. Most of the time it's the software itself -- at
least from a programmer point of view, but then from time to time it's
about the galaxy of things that happen around the software and that is
just as much fun.&lt;/p&gt;
&lt;p&gt;Kudos to the community for holding such a great event for so long now
-- &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Guadec"&gt;according to Wikipedia it dates back to 2000&lt;/a&gt;, I hope it will
continue to take place for the years to come.&lt;/p&gt;
</content><category term="Archives"/><category term="GUADEC"/><category term="Event"/></entry><entry><title>Fixing Ben NanoNote serial line</title><link href="https://apelete.missene.com/fixing-ben-nanonote-serial-line.html" rel="alternate"/><published>2014-05-04T00:00:00+02:00</published><updated>2024-08-15T19:17:03.334822+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-05-04:/fixing-ben-nanonote-serial-line.html</id><summary type="html">&lt;p&gt;The serial line soldered to my Ben NanoNote for debugging purpose
started to behave erratically. I was getting frequent disconnects
while in minicom or gdb. It happened before, but last week it got out
of hand and I couldn't get anything done by moving the wires a bit
like I …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The serial line soldered to my Ben NanoNote for debugging purpose
started to behave erratically. I was getting frequent disconnects
while in minicom or gdb. It happened before, but last week it got out
of hand and I couldn't get anything done by moving the wires a bit
like I used to.&lt;/p&gt;
&lt;p&gt;It was time to fix the rush job I did when I first soldered the wires
to get a serial line output.
At that time, two years ago, I had bought a (very) cheap soldering kit
off ebay to get the job done -- painful experience, I still remember.&lt;/p&gt;
&lt;p&gt;Since &lt;a class="reference external" href="http://apelete.missene.com/smt-soldering-tools.html"&gt;I recently upgraded my soldering tools&lt;/a&gt;, this was an
opportunity to wield the soldering iron again o/.&lt;/p&gt;
&lt;p&gt;First, I peeled off the adhesive tape that was holding the wires in
place in the Ben battery compartment to inspect the joints. The
problem exposed itself: the TX wire joint came off so easily with the
adhesive tape that I believe it was broken for some time already.&lt;/p&gt;
&lt;img alt="TXD pad is clear of the joint that broke" src="./pictures/ben-nanonote-txd-desoldered.jpg" /&gt;
&lt;p&gt;Anyway, let's clean the pad with some alcohol, apply some flux on it
and see how it goes.&lt;/p&gt;
&lt;p&gt;This time I put a drop of solder only on the tip of the wire to see if
it is easier than working with a tinned pad.&lt;/p&gt;
&lt;img alt="Almost perfect soldering of the TXD wire" src="./pictures/ben-nanonote-txd-resoldered.jpg" /&gt;
&lt;p&gt;Took me five minutes to set up everything and hey, it works !
Notice how the TXD joint is much more clean and regular than the other
two.&lt;/p&gt;
&lt;p&gt;Connection to the serial line seems to be reliable now, didn't
experienced any disconnect while working with the Ben, yay !&lt;/p&gt;
&lt;p&gt;&amp;quot;A bad workman blames his tools&amp;quot; they say, but let's be honest here:
to do good work, one must first have good tools ;-).&lt;/p&gt;
</content><category term="Archives"/><category term="Ben NanoNote"/><category term="Hardware"/></entry><entry><title>Linux 3.14 out, me contributions inside</title><link href="https://apelete.missene.com/linux-314-out-me-contributions-inside.html" rel="alternate"/><published>2014-04-06T00:00:00+02:00</published><updated>2024-08-15T19:17:16.150807+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-04-06:/linux-314-out-me-contributions-inside.html</id><summary type="html">&lt;p&gt;&lt;em&gt;Last edit on 2014-04-09: added details on the whatabouts.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lwn.net/Articles/592543/"&gt;Linus Torvalds released version 3.14 of the Linux kernel&lt;/a&gt; last week.&lt;/p&gt;
&lt;p&gt;Anything special this time around ? Well, first and foremost, I
managed to get a few patches inside \o/ (&amp;lt;-- hacker joy).&lt;/p&gt;
&lt;p&gt;Being part of the &lt;a class="reference external" href="http://en.qi-hardware.com/wiki/Qi-Hardware:About"&gt;Qi-Hardware&lt;/a&gt; community, I worked on …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Last edit on 2014-04-09: added details on the whatabouts.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://lwn.net/Articles/592543/"&gt;Linus Torvalds released version 3.14 of the Linux kernel&lt;/a&gt; last week.&lt;/p&gt;
&lt;p&gt;Anything special this time around ? Well, first and foremost, I
managed to get a few patches inside \o/ (&amp;lt;-- hacker joy).&lt;/p&gt;
&lt;p&gt;Being part of the &lt;a class="reference external" href="http://en.qi-hardware.com/wiki/Qi-Hardware:About"&gt;Qi-Hardware&lt;/a&gt; community, I worked on a USB device
driver for the &lt;a class="reference external" href="http://en.qi-hardware.com/wiki/Ben_NanoNote"&gt;Ben NanoNote&lt;/a&gt;. We were initially relying on an
out-of-tree device driver written by Ingenic for the USB device
controller of its JZ4740 SoC. In order to provide full upstream
support for the &lt;a class="reference external" href="http://en.qi-hardware.com/wiki/Ben_NanoNote"&gt;Ben NanoNote&lt;/a&gt; in the Linux kernel, I then wrote an
upstream compliant MUSB device driver which is feature-wise on par
with the initial one.&lt;/p&gt;
&lt;p&gt;My first contribution to the Linux kernel landed in version 3.13 in
fact. It was a small fix for the MUSB core, paving the way for the
following patches I worked on.&lt;/p&gt;
&lt;p&gt;In 3.14 it was all about &lt;a class="reference external" href="http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=10434d273ccdcee8eab4f5e08497d65841bbf354"&gt;adding support for the Ingenic JZ4740 USB
device controller&lt;/a&gt; through an MUSB device driver. Had to learn quite
a bit about the USB protocol and the Linux kernel internals on my
spare time, but it was worth the time and the effort -- let's be
honest here: I had a blast working on it late into the nights.&lt;/p&gt;
&lt;p&gt;Anyway, here are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;the aforementioned patches on kernel.org: &lt;a class="reference external" href="https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/log/?qt=author&amp;amp;q=apelete"&gt;https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/log/?qt=author&amp;amp;q=apelete&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;and a good summary of all the changes in Linux 3.14 -- it's a community effort after all :-): &lt;a class="reference external" href="http://kernelnewbies.org/Linux_3.14"&gt;http://kernelnewbies.org/Linux_3.14&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let's try to keep it up, and see what contributions land in the next
kernel releases ;-).&lt;/p&gt;
</content><category term="Archives"/><category term="Ben NanoNote"/><category term="Linux kernel"/></entry><entry><title>OpenEmbedded Coverage At FOSDEM 2014</title><link href="https://apelete.missene.com/openembedded-coverage-at-fosdem-2014.html" rel="alternate"/><published>2014-03-02T00:00:00+01:00</published><updated>2024-08-15T19:17:45.178771+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-03-02:/openembedded-coverage-at-fosdem-2014.html</id><summary type="html">&lt;p&gt;&lt;a class="reference external" href="https://fosdem.org/"&gt;FOSDEM&lt;/a&gt; 2014 took place a month ago in Brussels, Belgium, and the
event was once again a success, with over 5000 visitors attending
during the weekend. This year I was lucky enough to help the
&lt;a class="reference external" href="http://www.openembedded.org/"&gt;OpenEmbedded&lt;/a&gt; guys holding a booth during the event.&lt;/p&gt;
&lt;p&gt;I started contributing to OpenEmbedded while playing …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a class="reference external" href="https://fosdem.org/"&gt;FOSDEM&lt;/a&gt; 2014 took place a month ago in Brussels, Belgium, and the
event was once again a success, with over 5000 visitors attending
during the weekend. This year I was lucky enough to help the
&lt;a class="reference external" href="http://www.openembedded.org/"&gt;OpenEmbedded&lt;/a&gt; guys holding a booth during the event.&lt;/p&gt;
&lt;p&gt;I started contributing to OpenEmbedded while playing with the &lt;a class="reference external" href="http://en.qi-hardware.com/wiki/Ben_NanoNote"&gt;Ben
Nanonote&lt;/a&gt;, and I'm trying to keep up with new devices I lay my hands
on. I naturally went to the OpenEmbedded booth during FOSDEM, hoping
to see shiny new toys and say hello to the folks there.
Didn't put much thought into it before coming, but it turned out that
having one more guy help with the boot allowed the others to attend
some talks. We took turns during Sunday.&lt;/p&gt;
&lt;p&gt;We had the visit of Ken Fallon who was doing a coverage of FOSDEM for
&lt;a class="reference external" href="http://hackerpublicradio.org/"&gt;Hacker Public Radio&lt;/a&gt;. Listen and watch the &lt;a class="reference external" href="http://hackerpublicradio.org/eps.php?id=1453"&gt;whole OpenEmbedded
coverage on Hacker Public Radio&lt;/a&gt;.&lt;/p&gt;
&lt;img alt="Paul Eggleton and me at FOSDEM 2014" src="./pictures/paul_eggleton_and_me_fosdem_2014.jpg" /&gt;
&lt;p&gt;Paul Eggleton &amp;amp; me at FOSDEM 2014. Picture by Hacker Public Radio,
licensed under CC-BY-SA 3.0.&lt;/p&gt;
&lt;p&gt;It was an interesting experience, welcoming passersby and talking
about devices and the OpenEmbedded build system powering them --
people seemed more interested by the devices by the way, having more
to showcase might help spreading the word.&lt;/p&gt;
&lt;p&gt;I brought my Ben Nanonote to showcase on the stand, and felt psyched
that people were amazed by the tiny-ness of the Ben -- &amp;quot;cute&amp;quot; was the
word most of them used to describe it.
Beth Flanagan, release engineer at &lt;a class="reference external" href="https://www.yoctoproject.org/"&gt;Yocto Project&lt;/a&gt;, even took a
picture of the Ben sitting beside her 17inch-ish laptop, saying that
the discrepancy was &amp;quot;awesome&amp;quot; :-).&lt;/p&gt;
&lt;p&gt;Thanks to the OpenEmbedded community for holding the booth for a few
years now. They surely are a friendly bunch, welcoming and nice to
chat with.&lt;/p&gt;
&lt;p&gt;Let's hope we meet again next year.&lt;/p&gt;
</content><category term="Archives"/><category term="FOSDEM"/><category term="OpenEmbedded"/><category term="Event"/></entry><entry><title>Serial Console Output On GCW-Zero</title><link href="https://apelete.missene.com/serial-console-output-on-gcw-zero.html" rel="alternate"/><published>2014-03-02T00:00:00+01:00</published><updated>2024-08-15T19:17:50.702765+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-03-02:/serial-console-output-on-gcw-zero.html</id><summary type="html">&lt;p&gt;I recently bought a &lt;a class="reference external" href="http://www.gcw-zero.com/"&gt;GCW-Zero&lt;/a&gt; to play with in my spare time.&lt;/p&gt;
&lt;p&gt;My interest being in hardware related issues, I will be needing a
serial console output to debug low level code. It turns out this
hardware feature is missing on the GCW-Zero out of the box, as it's
often …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently bought a &lt;a class="reference external" href="http://www.gcw-zero.com/"&gt;GCW-Zero&lt;/a&gt; to play with in my spare time.&lt;/p&gt;
&lt;p&gt;My interest being in hardware related issues, I will be needing a
serial console output to debug low level code. It turns out this
hardware feature is missing on the GCW-Zero out of the box, as it's
often the case with embedded products.
How come even a product made by geeks for geeks is missing this ?
&lt;strong&gt;Embedded devices should have serial console output pins soldered on
their&lt;/strong&gt; &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Printed_circuit_board"&gt;PCB&lt;/a&gt; &lt;strong&gt;out of factory&lt;/strong&gt;, me think.&lt;/p&gt;
&lt;p&gt;Anyway, game-play level 0 comes down to soldering a serial console
output to the board.&lt;/p&gt;
&lt;div class="section" id="materials-techniques-tools"&gt;
&lt;h2&gt;Materials, techniques &amp;amp; tools&lt;/h2&gt;
&lt;p&gt;For this purpose, here is a list of what you will need:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;GCW-Zero unit (obviously),&lt;/li&gt;
&lt;li&gt;Flat screwdriver #1.5,&lt;/li&gt;
&lt;li&gt;Philips screwdriver #00,&lt;/li&gt;
&lt;li&gt;Soldering station,&lt;/li&gt;
&lt;li&gt;Conical type of soldering tip 0.4mm diameter,&lt;/li&gt;
&lt;li&gt;Soldering wire 0.5mm diameter,&lt;/li&gt;
&lt;li&gt;Wire-wrapping wire 30AWG,&lt;/li&gt;
&lt;li&gt;3.3V USB to serial RS232 converter,&lt;/li&gt;
&lt;li&gt;4 Crocodile clips (optional),&lt;/li&gt;
&lt;li&gt;4 Dupont wire cables with pin headers (optional).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The GCW-Zero PCB is crowded with teeny components, thus the tiny
diameter of materials and tools above. The screwdrivers will help open
the case, sealed by 4 small screws on the back.&lt;/p&gt;
&lt;p&gt;Regarding the soldering tip, a 0.8mm diameter one might be workable if
you're skilled enough -- I used a 0.4mm tip, better be safe than
sorry. Have a look at my &lt;a class="reference external" href="http://apelete.missene.com/smt-soldering-tools.html"&gt;SMT soldering tools post&lt;/a&gt; for further
details.&lt;/p&gt;
&lt;p&gt;Connecting the serial output to your computer is what the USB to
serial converter is for. I got a cheap one off eBay:&lt;/p&gt;
&lt;img alt="Dual voltage USB to serial converter" src="./pictures/usb-to-rs232-uart-converter.jpg" /&gt;
&lt;p&gt;As shown on the picture above, this converter has a 5 pins connector:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;RX for receiving data,&lt;/li&gt;
&lt;li&gt;TX for transmitting data,&lt;/li&gt;
&lt;li&gt;GND for ground line,&lt;/li&gt;
&lt;li&gt;3.3V for powering the serial output,&lt;/li&gt;
&lt;li&gt;5V for powering the serial output.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Having both 3.3V and 5V pins will allow you to choose the voltage
depending on your needs, should you ever plan to reuse the converter
for another device.&lt;/p&gt;
&lt;p&gt;Wrapping up the materials and tools list are the crocodile
clips.&lt;/p&gt;
&lt;img alt="4 colours crocodile clips" src="./pictures/crocodile-clips.jpg" /&gt;
&lt;p&gt;These ones are optional if you choose to solder the USB to serial
converter to the GCW-Zero.
I use the clips to avoid soldering the converter: result is messier
due to more cables, but clips are easily detached to allow me to tuck
wires away and keep the device portable.&lt;/p&gt;
&lt;img alt="Dupont wire cable with pin headers set" src="./pictures/pin-headers-dupont-wire-cable-set.jpg" /&gt;
&lt;p&gt;Going with the crocodile clips, I also use Dupont wire cables and pin
headers to space out the USB converter pins which are too close to be
grabbed individually with the clips.&lt;/p&gt;
&lt;p&gt;A good place to start learning about soldering techniques is the
&lt;a class="reference external" href="https://www.youtube.com/user/EEVblog"&gt;EEVblog on Youtube&lt;/a&gt;. David L. Jones shot a three parts soldering
tutorial there:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.youtube.com/watch?v=J5Sb21qbpEQ"&gt;EEVblog Soldering Tutorial Part 1 - Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.youtube.com/watch?v=fYz5nIHH0iY"&gt;EEVblog Soldering Tutorial Part 2 - Through Hole&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.youtube.com/watch?v=b9FC9fAlfQE"&gt;EEVblog Soldering Tutorial Part 3 - Surface Mount&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not being an expert solderer myself, I cannot tell much more on the
subject than you'll learn watching those videos. And practicing.&lt;/p&gt;
&lt;p&gt;Tinning the wire-wrapping wires and the pads on the PCB is important
though. Let's cut to the chase.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="down-the-rabbit-hole"&gt;
&lt;h2&gt;Down the rabbit hole&lt;/h2&gt;
&lt;p&gt;On the back of the device are four cylindrical rubber pads you need to
pull out to reveal the screws underneath -- using the flat screwdriver
should help.&lt;/p&gt;
&lt;img alt="GCW-Zero back with screw holes" src="./pictures/gcwzero-back-screw-holes.jpg" /&gt;
&lt;p&gt;After removing the screws with the Philips screwdriver, gently detach
the black back cover from the case to pry it open -- you can use the
flat screwdriver by inserting the blade alongside the case; I just
used my fingernails.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Be careful&lt;/strong&gt; with the shoulder buttons and be aware that the battery
is glued onto the inside of the back cover (on its right side) while
being soldered to the PCB by two thin wires: you probably don't want
to break these, unless you're ok with fixing it later.&lt;/p&gt;
&lt;img alt="GCW-Zero PCB overview" src="./pictures/gcwzero-pcb.jpg" /&gt;
&lt;p&gt;There you have it, the GCW-Zero PCB in its full glory. Notice the
black back cover on the right side of the picture: I didn't completely
remove the back cover due to the battery being soldered to the board
as mentioned earlier.&lt;/p&gt;
&lt;img alt="GCW-Zero PCB closeup" src="./pictures/gcwzero-pcb-closeup.jpg" /&gt;
&lt;p&gt;Looking closer, you can see 4 test points below the Ingenic JZ4770
SoC: RX, TX, GND and 3.3v. That's where you'll need to solder the
wires to get a serial output.&lt;/p&gt;
&lt;img alt="GCW-Zero tinned pads" src="./pictures/gcwzero-tined-pads.jpg" /&gt;
&lt;p&gt;You must first tin the test points by dropping a small amount of
solder onto them.&lt;/p&gt;
&lt;p&gt;Strip away the tip of the insulation of your wire-wrapping wire, and
slightly coat the strand with solder too.&lt;/p&gt;
&lt;p&gt;Having tinned both the pads on the board and the wires, you should now
be ready to solder the wires to each of the test points. It's
sometimes recommended to slightly tin the tip of the soldering iron to
help conduct heat to the components, which I did by the way, but I'm
not sure if that is advisable here, due to the small pads size.&lt;/p&gt;
&lt;img alt="GCW-Zero closeup of RX, TX and 3.3v wires" src="./pictures/gcwzero-rxtx3v-closeup-hd-2.jpg" /&gt;
&lt;p&gt;I used a little too much solder during the process indeed, resulting
in bigger solder joints than needed as you can see above.&lt;/p&gt;
&lt;p&gt;Watch out for the green wire which is way too much close to that
capacitor: a little push and it will short RX, making the problem hard
to find out.&lt;/p&gt;
&lt;p&gt;I also had a hard time soldering the GND test point. Despite many
tries I couldn't get the solder to stick to the pad, and having less
space to work with due to the other test points around didn't help
either -- maybe starting with TX and GND and then soldering RX and
3.3v would have made it easier.&lt;/p&gt;
&lt;p&gt;Since GND is used for ground connection anyway, I ultimately resorted
to soldering it to the large pad next to the GCW-Zero logo.&lt;/p&gt;
&lt;img alt="GCW-Zero closeup of GND wire" src="./pictures/gcwzero-gnd-closeup.jpg" /&gt;
&lt;p&gt;Too much solder on this joint too, and I'm missing a small wire cutter
to cut that strand off.&lt;/p&gt;
&lt;img alt="GCW-Zero serial wires overview" src="./pictures/gcwzero-serial-wires-overview.jpg" /&gt;
&lt;p&gt;Big picture looks good. Not exactly pretty but good enough will do.&lt;/p&gt;
&lt;p&gt;Don't know if this is a well spread practice but, as you've already
noticed, I used the following wire colour code:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Whi&lt;strong&gt;t&lt;/strong&gt;e for &lt;strong&gt;T&lt;/strong&gt;X,&lt;/li&gt;
&lt;li&gt;G&lt;strong&gt;r&lt;/strong&gt;een for &lt;strong&gt;R&lt;/strong&gt;X,&lt;/li&gt;
&lt;li&gt;Black for GND,&lt;/li&gt;
&lt;li&gt;Red for Power (3.3v).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cleaning everything up:&lt;/p&gt;
&lt;img alt="GCW-Zero wires glued and passed through speaker grill" src="./pictures/gcwzero-glued-wires-through-grill.jpg" /&gt;
&lt;p&gt;To hold everything in place and tidy up a bit, I glued the wires ontop
of the MicroSD card holder, removed the speaker grill on the bottom
left -- gently pushed it inward from the outside, it came off easily
-- and passed the wires through.&lt;/p&gt;
&lt;img alt="GCW-Zero serial output console final contraption" src="./pictures/gcwzero-serial-output-contraption.jpg" /&gt;
&lt;p&gt;Looking at the final contraption, with the wires attached to the USB
converter using the crocodile clips, and extended with pin headers and
Dupont cables.&lt;/p&gt;
&lt;p&gt;Notice two things in the picture above:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;RX and TX wires are respectively attached to TX and RX USB
converter pins,&lt;/li&gt;
&lt;li&gt;It still boots ;-).&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="serial-console-software-wonderland"&gt;
&lt;h2&gt;Serial console software wonderland&lt;/h2&gt;
&lt;p&gt;With the GCW-Zero now enabled with a serial output, hook it up to a
computer running your favourite serial console software:&lt;/p&gt;
&lt;img alt="GCW-Zero boot process displayed in Minicom" src="./pictures/screenshot-gcwzero-boot-serial-top.png" /&gt;
&lt;p&gt;Hocus pocus. Initially on the 3.5&amp;quot; screen, Linux boot process is now
displayed on a 23&amp;quot; screen here through serial console output.&lt;/p&gt;
&lt;p&gt;Software configuration is as follow:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;57600 Bits/s baud rate,&lt;/li&gt;
&lt;li&gt;8 bits data, No parity, 1 stop bit (8N1),&lt;/li&gt;
&lt;li&gt;No hardware flow control,&lt;/li&gt;
&lt;li&gt;No software flow control.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enjoy the beauty of having the terminal at the end of the boot process
at your fingertips.&lt;/p&gt;
&lt;p&gt;Level 0 complete. Happy hacking :-).&lt;/p&gt;
&lt;/div&gt;
</content><category term="Archives"/><category term="GCW-Zero"/><category term="Hardware"/></entry><entry><title>SMT Soldering Tools</title><link href="https://apelete.missene.com/smt-soldering-tools.html" rel="alternate"/><published>2014-02-23T00:00:00+01:00</published><updated>2024-08-15T19:17:56.298758+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-02-23:/smt-soldering-tools.html</id><summary type="html">&lt;p&gt;&lt;em&gt;Last edit on 2014-03-02: added a glue gun section.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A year ago, I had to solder a serial console output to the &lt;a class="reference external" href="http://en.qi-hardware.com/wiki/Ben_NanoNote"&gt;Ben
Nanonote&lt;/a&gt; in order to hack its Linux kernel.&lt;/p&gt;
&lt;p&gt;Went the cheap way back then, and bought a soldering kit off eBay
that got the job done, albeit …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Last edit on 2014-03-02: added a glue gun section.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A year ago, I had to solder a serial console output to the &lt;a class="reference external" href="http://en.qi-hardware.com/wiki/Ben_NanoNote"&gt;Ben
Nanonote&lt;/a&gt; in order to hack its Linux kernel.&lt;/p&gt;
&lt;p&gt;Went the cheap way back then, and bought a soldering kit off eBay
that got the job done, albeit painfully.
I remember the guys at &lt;a class="reference external" href="http://en.qi-hardware.com/wiki/Qi-Hardware:About"&gt;Qi-Hardware&lt;/a&gt; making fun of me, for it took me
ages to solder 3 wires on the device: &amp;quot;Were you using candles to melt
the tin ?&amp;quot; :-).&lt;/p&gt;
&lt;p&gt;I'm now planning to hack the &lt;a class="reference external" href="http://www.gcw-zero.com/"&gt;GCW Zero&lt;/a&gt;, and thought it may be time
to invest in proper soldering tools for &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Surface-mount_technology"&gt;surface-mount technology&lt;/a&gt; (SMT).
For the record, here is a breakdown of the gear I will be using from
now on.&lt;/p&gt;
&lt;div class="section" id="soldering-station"&gt;
&lt;h2&gt;Soldering station&lt;/h2&gt;
&lt;p&gt;Out is the cheapo 30W soldering iron, welcome the &lt;a class="reference external" href="http://www.howardelectronics.com/xytronic/lf389D.html"&gt;Xytronic LF-389D
soldering station&lt;/a&gt;.&lt;/p&gt;
&lt;img alt="Xytronic LF-389D soldering station" src="./pictures/soldering-station-on.jpg" /&gt;
&lt;p&gt;It's affordable, quite small and feels sturdy.&lt;/p&gt;
&lt;p&gt;Having more power (it's a 60W unit) means it can heat up quicker,
recover from a heat loss more rapidly, maintain higher temperatures
and heat larger areas. And the iron temperature can be set as needed.&lt;/p&gt;
&lt;p&gt;Bought it from &lt;a class="reference external" href="https://www.elfa.se"&gt;Elfa Distrelec&lt;/a&gt; since I needed a European plug and
220-240V power supply.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="additional-iron-tips"&gt;
&lt;h2&gt;Additional iron tips&lt;/h2&gt;
&lt;p&gt;SMT means small electronic components to work with.
Along the soldering station, I also bought 2 additional soldering
tips.&lt;/p&gt;
&lt;img alt="Xytronic LF-389D soldering tips" src="./pictures/soldering-tips.jpg" /&gt;
&lt;p&gt;From left to right:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Soldering tip Chisel shaped 1.2mm (ref. XYB06),&lt;/li&gt;
&lt;li&gt;Soldering tip Conical 0.4mm (ref. XYB03),&lt;/li&gt;
&lt;li&gt;Soldering tip Conical 0.8mm (ref. XYB01, sold with Xytronic LF-389D).&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="soldering-wire"&gt;
&lt;h2&gt;Soldering wire&lt;/h2&gt;
&lt;p&gt;Lo and behold, all solder formulae are not made equal either.&lt;/p&gt;
&lt;img alt="Stannol Sn62Pb36Ag2 solder" src="./pictures/stannol-solder.jpg" /&gt;
&lt;p&gt;This one is a manufactured by Stannol and has an Sn62Pb36Ag2 chemical
formula, which reads 62% Sn, 36% Pb and 2% Ag.&lt;/p&gt;
&lt;p&gt;Having lead in the solder means a lower melting temperature to work
at, decreasing the risk of damaging components. This specific formula
is designed by the manufacturer to be used with surface-mount devices
(SMD), so it seems to be a perfect match for SMT work.
Regarding health and &lt;a class="reference external" href="https://en.wikipedia.org/wiki/ROHS"&gt;RoHS directive&lt;/a&gt; in the European Union, this
should be ok since the solder will be used in small amounts for
personal hardware modifications, nothing industrial or to be sold (in
which case it's recommended to use lead-free solder).&lt;/p&gt;
&lt;p&gt;Thickness of the solder wire is another important parameter.
For SMT, thin (&amp;lt; 0.7mm) is preferable since it makes it easier to drop
small amounts of solder at once. 250g of 0.5mm solder wire should be
aplenty.&lt;/p&gt;
&lt;p&gt;Bought it from &lt;a class="reference external" href="http://www.pkelektronik.com/"&gt;pkelektronik.com&lt;/a&gt;, I couldn't find it elsewhere.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="flux"&gt;
&lt;h2&gt;Flux&lt;/h2&gt;
&lt;p&gt;&amp;quot;And don't forget the flux: it's the SMT-solderer's best friend&amp;quot; I was
told :-).&lt;/p&gt;
&lt;img alt="Stannol flux pen" src="./pictures/stannol-flux-pen.jpg" /&gt;
&lt;p&gt;In order of convenience: marker pen &amp;gt; ballpoint pen &amp;gt; syringe &amp;gt; paste
&amp;gt; powder. Of course, this also depends on what you're working on.&lt;/p&gt;
&lt;p&gt;Flux is an acid that helps removing oxides and reducing the surface
tension of the tin in the solder (the Sn component), preventing it to
form little balls that do not stick to the metal you're working on.&lt;/p&gt;
&lt;p&gt;There is 3 basic types of flux: RA/RMA, water-soluble and no-clean:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Rosin Activated (RA) is the most vigorous type, but it's very sticky
and a pain to remove from &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Printed_circuit_board"&gt;PCB&lt;/a&gt; (and it must be removed since acid
attacks metals). Rosin Midly Activated (RMA) is less strong than RA
but still in the same ballpark,&lt;/li&gt;
&lt;li&gt;Water-soluble means &amp;quot;hot demineralized water under high
pressure&amp;quot;. Not quite as easy to get rid of at it may sound, but it's
feasible. Use a cheap ultrasonic cleaner for that,&lt;/li&gt;
&lt;li&gt;No-clean promises that you don't need to clean up but you should be
careful with such statements. It's the weakest of the three though.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When it comes to flux formulae (yeah, flux is a field of its own),
better use F-SW33 or F-SW34 types (better the latter). Stay away from
all F-SW1x and F-SW2x and avoid F-SW31/32 Rosin flux if possible.
This does not tell all the truth about flux though: you should
get a non-activated no-clean no-rosin flux, but it still needs
explicit classification &amp;quot;for SMT&amp;quot; by manufacturer. Trial and error,
and collecting different types of flux for different purposes seems
the only way to go here.&lt;/p&gt;
&lt;p&gt;Stannol X32-10i is an F-SW33 no-clean type, but I will be using
alcohol to clean the PCB after I'm done.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="wire-wrapping-wire"&gt;
&lt;h2&gt;Wire-wrapping wire&lt;/h2&gt;
&lt;p&gt;Not much to say about that one.&lt;/p&gt;
&lt;img alt="30AWG Olympic wire rings" src="./pictures/soldering-wire-30awg.jpg" /&gt;
&lt;p&gt;Thinness is the key factor here, so I went for &lt;a class="reference external" href="https://en.wikipedia.org/wiki/AWG"&gt;30AWG&lt;/a&gt; &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Kynar"&gt;Kynar&lt;/a&gt; wires.
Also bought different colours to make it easier to tell which is
connected to what.&lt;/p&gt;
&lt;p&gt;Bought it from eBay (love that place).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="glue-gun"&gt;
&lt;h2&gt;Glue gun&lt;/h2&gt;
&lt;p&gt;A useful, affordable tool for finishing touches.&lt;/p&gt;
&lt;img alt="Steinel Gluematic 3002 glue gun" src="./pictures/steinel-glue-gun.jpg" /&gt;
&lt;p&gt;Not directly related to soldering, using a glue gun can be useful to
glue wires in place once the job is done. Nothing moves beyond the
glue point, preventing wires and joints from being stressed.&lt;/p&gt;
&lt;p&gt;Many thanks to Werner Almesberger and Joerg Reisenweber for the
invaluable insight and the funny talk.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Archives"/><category term="Hardware"/></entry><entry><title>Writing An MUSB Glue Layer</title><link href="https://apelete.missene.com/writing-an-musb-glue-layer.html" rel="alternate"/><published>2014-02-09T00:00:00+01:00</published><updated>2024-08-15T19:18:02.690750+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2014-02-09:/writing-an-musb-glue-layer.html</id><summary type="html">&lt;p&gt;&lt;em&gt;Last edit on 2014-06-29: I submitted this documentation upstream and&lt;/em&gt;
&lt;em&gt;it has been accepted into Linux kernel 3.16-rc1.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can read it from the Linux kernel source at&lt;/em&gt;
&lt;a class="reference external" href="https://www.kernel.org/doc/htmldocs/writing_musb_glue_layer/index.html"&gt;https://www.kernel.org/doc/htmldocs/writing_musb_glue_layer/index.html&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Copyright © 2014 Apelete Seketeli &amp;lt;apelete at seketeli.net&amp;gt;&lt;/p&gt;
&lt;p&gt;This documentation is free …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;em&gt;Last edit on 2014-06-29: I submitted this documentation upstream and&lt;/em&gt;
&lt;em&gt;it has been accepted into Linux kernel 3.16-rc1.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can read it from the Linux kernel source at&lt;/em&gt;
&lt;a class="reference external" href="https://www.kernel.org/doc/htmldocs/writing_musb_glue_layer/index.html"&gt;https://www.kernel.org/doc/htmldocs/writing_musb_glue_layer/index.html&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Copyright © 2014 Apelete Seketeli &amp;lt;apelete at seketeli.net&amp;gt;&lt;/p&gt;
&lt;p&gt;This documentation is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.&lt;/p&gt;
&lt;p&gt;This documentation is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.&lt;/p&gt;
&lt;p&gt;You should have received a copy of the GNU General Public License
along with this documentation; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.&lt;/p&gt;
&lt;p&gt;For more details see the file COPYING in the Linux kernel source tree.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="table-of-contents"&gt;
&lt;h2&gt;Table Of Contents&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#chapter-1-introduction"&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#chapter-2-linux-musb-basics"&gt;Linux MUSB Basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#chapter-3-handling-irqs"&gt;Handling IRQs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#chapter-4-device-platform-data"&gt;Device Platform Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#chapter-5-device-quirks"&gt;Device Quirks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#chapter-6-conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#chapter-7-acknowledgements"&gt;Acknowledgements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#resources"&gt;Resources&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="chapter-1-introduction"&gt;
&lt;h2&gt;Chapter 1 - Introduction&lt;/h2&gt;
&lt;!-- DONE:
- Difference between MUSB and USB
- Overview of MUSBHDRC --&gt;
&lt;p&gt;The Linux MUSB subsystem is part of the larger Linux USB subsystem.
It provides support for embedded USB Device Controllers (UDC) that do
not use Universal Host Controller Interface (UHCI) or Open Host
Controller Interface (OHCI).&lt;/p&gt;
&lt;p&gt;Instead, these embedded UDC rely on the USB On-the-Go (OTG)
specification which they implement at least partially.
The silicon reference design used in most cases is the Multipoint USB
Highspeed Dual-Role Controller (MUSB HDRC) found in the Mentor
Graphics Inventra™ design.&lt;/p&gt;
&lt;!-- DONE:
- Why I wrote this document --&gt;
&lt;p&gt;As a self-taught exercise I have written an MUSB glue layer for the
Ingenic JZ4740 SoC, modelled after the many MUSB glue layers in the
kernel source tree. This layer can be found at
drivers/usb/musb/jz4740.c.
In this documentation I will walk through the basics of the jz4740.c
glue layer, explaining the different pieces and what needs to be done
in order to write your own device glue layer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="chapter-2-linux-musb-basics"&gt;
&lt;h2&gt;Chapter 2 - Linux MUSB Basics&lt;/h2&gt;
&lt;p&gt;To get started on the topic, please read USB On-the-Go Basics (see
Resources) which provides an introduction of USB OTG operation at the
hardware level. A couple of wiki pages by Texas Instruments and Analog
Devices also provide an overview of the Linux kernel MUSB
configuration, albeit focused on some specific devices provided by
these companies.
Finally, getting acquainted with the USB specification at USB home
page may come in handy, with practical instance provided through the
Writing USB Device Drivers documentation (again, see Resources).&lt;/p&gt;
&lt;p&gt;Linux USB stack is a layered architecture in which the MUSB controller
hardware sits at the lowest. The MUSB controller driver abstract the
MUSB controller hardware to the Linux USB stack.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
    ------------------------
    |                      | &amp;lt;------- drivers/usb/gadget
    | Linux USB Core Stack | &amp;lt;------- drivers/usb/host
    |                      | &amp;lt;------- drivers/usb/core
    ------------------------
               ⬍
   --------------------------
   |                        | &amp;lt;------ drivers/usb/musb/musb_gadget.c
   | MUSB Controller driver | &amp;lt;------ drivers/usb/musb/musb_host.c
   |                        | &amp;lt;------ drivers/usb/musb/musb_core.c
   --------------------------
               ⬍
---------------------------------
| MUSB Platform Specific Driver |
|                               | &amp;lt;-- drivers/usb/musb/jz4740.c
|       aka &amp;quot;Glue Layer&amp;quot;        |
---------------------------------
               ⬍
---------------------------------
|   MUSB Controller Hardware    |
---------------------------------
&lt;/pre&gt;
&lt;p&gt;As outlined above, the glue layer is actually the platform specific
code sitting in between the controller driver and the controller
hardware.&lt;/p&gt;
&lt;p&gt;Just like a Linux USB driver needs to register itself with the Linux
USB subsystem, the MUSB glue layer needs first to register itself with
the MUSB controller driver. This will allow the controller driver to
know about which device the glue layer supports and which functions to
call when a supported device is detected or released; remember we are
talking about an embedded controller chip here, so no insertion or
removal at run-time.&lt;/p&gt;
&lt;p&gt;All of this information is passed to the MUSB controller driver
through a platform_driver structure defined in the glue layer as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;
&lt;span class="normal"&gt;7&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;platform_driver&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_driver&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;probe&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_probe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_remove&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;musb-jz4740&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The probe and remove function pointers are called when a matching
device is detected and, respectively, released.
The name string describes the device supported by this glue layer. In
the current case it matches a platform_device structure declared in
arch/mips/jz4740/platform.c.
Note that we are not using device tree bindings here.&lt;/p&gt;
&lt;p&gt;In order to register itself to the controller driver, the glue layer
goes through a few steps, basically allocating the controller hardware
resources and initialising a couple of circuits.
To do so, it needs to keep track of the information used throughout
these steps. This is done by defining a private jz4740_glue structure:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;jz4740_glue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;device&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;platform_device&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;clk&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The dev and musb members are both device structure variables. The
first one holds generic information about the device, since it's the
basic device structure, and the latter holds information more closely
related to the subsystem the device is registered to.
The clk variable keeps information related to the device clock
operation.&lt;/p&gt;
&lt;!-- DONE:
- Go through probe() operation --&gt;
&lt;p&gt;Let's go through the steps of the probe function that leads the glue
layer to register itself to the controller driver.&lt;/p&gt;
&lt;p&gt;N.B.: For the sake of readability each function will be split in
logical parts, each part being shown as if it was independent from the
others.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;
&lt;span class="normal"&gt;24&lt;/span&gt;
&lt;span class="normal"&gt;25&lt;/span&gt;
&lt;span class="normal"&gt;26&lt;/span&gt;
&lt;span class="normal"&gt;27&lt;/span&gt;
&lt;span class="normal"&gt;28&lt;/span&gt;
&lt;span class="normal"&gt;29&lt;/span&gt;
&lt;span class="normal"&gt;30&lt;/span&gt;
&lt;span class="normal"&gt;31&lt;/span&gt;
&lt;span class="normal"&gt;32&lt;/span&gt;
&lt;span class="normal"&gt;33&lt;/span&gt;
&lt;span class="normal"&gt;34&lt;/span&gt;
&lt;span class="normal"&gt;35&lt;/span&gt;
&lt;span class="normal"&gt;36&lt;/span&gt;
&lt;span class="normal"&gt;37&lt;/span&gt;
&lt;span class="normal"&gt;38&lt;/span&gt;
&lt;span class="normal"&gt;39&lt;/span&gt;
&lt;span class="normal"&gt;40&lt;/span&gt;
&lt;span class="normal"&gt;41&lt;/span&gt;
&lt;span class="normal"&gt;42&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_probe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;platform_device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;platform_device&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;jz4740_glue&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;clk&lt;/span&gt;&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;                             &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;devm_kzalloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GFP_KERNEL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ENOMEM&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;platform_device_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;musb-hdrc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PLATFORM_DEVID_AUTO&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;dev_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;failed to allocate musb device&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ENOMEM&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;devm_clk_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;udc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IS_ERR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;dev_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;failed to get clock&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PTR_ERR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;err_platform_device_put&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clk_prepare_enable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;dev_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;failed to enable clock&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;err_platform_device_put&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nl"&gt;err_platform_device_put&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;platform_device_put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The first few lines of the probe function allocate and assign the
glue, musb and clk variables.
The GFP_KERNEL flag (line 8) allows the allocation process to sleep
and wait for memory, thus being usable in a blocking situation. The
PLATFORM_DEVID_AUTO flag (line 12) allows automatic allocation and
management of device IDs in order to avoid device namespace collisions
with explicit IDs. With devm_clk_get() (line 18) the glue layer
allocates the clock -- the &lt;tt class="docutils literal"&gt;devm_&lt;/tt&gt; prefix indicates that clk_get()
is managed: it automatically frees the allocated clock resource data
when the device is released -- and enable it.&lt;/p&gt;
&lt;p&gt;Then comes the registration steps:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;
&lt;span class="normal"&gt;24&lt;/span&gt;
&lt;span class="normal"&gt;25&lt;/span&gt;
&lt;span class="normal"&gt;26&lt;/span&gt;
&lt;span class="normal"&gt;27&lt;/span&gt;
&lt;span class="normal"&gt;28&lt;/span&gt;
&lt;span class="normal"&gt;29&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_probe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;platform_device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb_hdrc_platform_data&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pdata&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_platform_data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;pdata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;platform_ops&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_ops&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;platform_set_drvdata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;platform_device_add_resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                            &lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;num_resources&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;dev_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;failed to add resources&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;err_clk_disable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;platform_device_add_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pdata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pdata&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;dev_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;failed to add platform_data&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;err_clk_disable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nl"&gt;err_clk_disable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;clk_disable_unprepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;err_platform_device_put&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;platform_device_put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The first step is to pass the device data privately held by the glue
layer on to the controller driver through platform_set_drvdata() (line
7).
Next is passing on the device resources information, also privately
held at that point, through platform_device_add_resources() (line 9).&lt;/p&gt;
&lt;p&gt;Finally comes passing on the platform specific data to the controller
driver (line 16). Platform data will be discussed in &lt;a class="reference internal" href="#chapter-4-device-platform-data"&gt;Chapter 4&lt;/a&gt;, but
here we are looking at the platform_ops function pointer (line 5) in
musb_hdrc_platform_data structure (line 3). This function pointer
allows the MUSB controller driver to know which function to call for
device operation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb_platform_ops&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_ops&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_init&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_exit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Here we have the minimal case where only init and exit functions are
called by the controller driver when needed.
Fact is the JZ4740 MUSB controller is a basic controller, lacking some
features found in other controllers, otherwise we may also have
pointers to a few other functions like a power management function or
a function to switch between OTG and non-OTG modes, for instance.&lt;/p&gt;
&lt;p&gt;At that point of the registration process, the controller driver
actually calls the init function:&lt;/p&gt;
&lt;!-- DONE:
- Step into init() operation just after platform_device_add_data() --&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_musb_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xceiv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;usb_get_phy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USB_PHY_TYPE_USB2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xceiv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;pr_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;HS UDC: no transceiver configured&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ENODEV&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* Silicon does not implement ConfigData register.&lt;/span&gt;
&lt;span class="cm"&gt;         * Set dyn_fifo to avoid reading EP config from hardware.&lt;/span&gt;
&lt;span class="cm"&gt;         */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dyn_fifo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;isr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_interrupt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The goal of jz4740_musb_init() is to get hold of the transceiver
driver data of the MUSB controller hardware and pass it on to the MUSB
controller driver, as usual.
The transceiver is the circuitry inside the controller hardware
responsible for sending/receiving the USB data. Since it is an
implementation of the physical layer of the OSI model, the transceiver
is also referred to as PHY.&lt;/p&gt;
&lt;p&gt;Getting hold of the MUSB PHY driver data is done with usb_get_phy()
which returns a pointer to the structure containing the driver
instance data.
The next couple of instructions (line 12 and 14) are used as a quirk
and to setup IRQ handling respectively. Quirks and IRQ handling will
be discussed later in &lt;a class="reference internal" href="#chapter-5-device-quirks"&gt;Chapter 5&lt;/a&gt; and &lt;a class="reference internal" href="#chapter-3-handling-irqs"&gt;Chapter 3&lt;/a&gt;.&lt;/p&gt;
&lt;!-- DONE:
- Go through exit() counterpart --&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_musb_exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;usb_put_phy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xceiv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Acting as the counterpart of init, the exit function releases the MUSB
PHY driver when the controller hardware itself is about to be
released.&lt;/p&gt;
&lt;p&gt;Again, note that init and exit are fairly simple in this case due to
the basic set of features of the JZ4740 controller hardware. When
writing an musb glue layer for a more complex controller hardware, you
might need to take care of more processing in those two functions.&lt;/p&gt;
&lt;!-- DONE:
- Finish probe() --&gt;
&lt;p&gt;Returning from the init function, the MUSB controller driver jumps
back into the probe function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_probe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;platform_device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;platform_device_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;dev_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;failed to register musb device&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;err_clk_disable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nl"&gt;err_clk_disable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;clk_disable_unprepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;err_platform_device_put&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;platform_device_put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;This is the last part of the device registration process where the
glue layer adds the controller hardware device to Linux kernel device
hierarchy: at this stage, all known information about the device is
passed on to the Linux USB core stack.&lt;/p&gt;
&lt;!-- DONE:
- Go through remove() counterpart --&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;
&lt;span class="normal"&gt;7&lt;/span&gt;
&lt;span class="normal"&gt;8&lt;/span&gt;
&lt;span class="normal"&gt;9&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;platform_device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;jz4740_glue&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;platform_get_drvdata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdev&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;platform_device_unregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;clk_disable_unprepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;glue&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;clk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Acting as the counterpart of probe, the remove function unregister the
MUSB controller hardware (line 5) and disable the clock (line 6),
allowing it to be gated.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="chapter-3-handling-irqs"&gt;
&lt;h2&gt;Chapter 3 - Handling IRQs&lt;/h2&gt;
&lt;p&gt;Additionally to the MUSB controller hardware basic setup and
registration, the glue layer is also responsible for handling the
IRQs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;
&lt;span class="normal"&gt;24&lt;/span&gt;
&lt;span class="normal"&gt;25&lt;/span&gt;
&lt;span class="normal"&gt;26&lt;/span&gt;
&lt;span class="normal"&gt;27&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;irqreturn_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_musb_interrupt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;irq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;__hci&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;irqreturn_t&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;retval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IRQ_NONE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__hci&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;spin_lock_irqsave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_usb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb_readb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mregs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTRUSB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_tx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb_readw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mregs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTRTX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_rx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb_readw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mregs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTRRX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;         * The controller is gadget only, the state of the host mode IRQ bits is&lt;/span&gt;
&lt;span class="cm"&gt;         * undefined. Mask them to make sure that the musb driver core will&lt;/span&gt;
&lt;span class="cm"&gt;         * never see them set&lt;/span&gt;
&lt;span class="cm"&gt;         */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_usb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTR_SUSPEND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTR_RESUME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTR_RESET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTR_SOF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_usb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_tx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;retval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb_interrupt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;spin_unlock_irqrestore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;retval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Here the glue layer mostly has to read the relevant hardware registers
and pass their values on to the controller driver which will handle
the actual event that triggered the IRQ.&lt;/p&gt;
&lt;!-- DONE:
- explain spin_lock_irqsave()
- explain MUSB_INTRUSB, MUSB_INTRTX and MUSB_INTRRX registers
- mention musb-&gt;int_usb quirks --&gt;
&lt;p&gt;The interrupt handler critical section is protected by the
spin_lock_irqsave() and counterpart spin_unlock_irqrestore() functions
(line 7 and 24 respectively), which prevent the interrupt handler code
to be run by two different threads at the same time.&lt;/p&gt;
&lt;p&gt;Then the relevant interrupt registers are read (line 9 to 11):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;MUSB_INTRUSB: indicates which USB interrupts are currently active,&lt;/li&gt;
&lt;li&gt;MUSB_INTRTX: indicates which of the interrupts for TX endpoints are
currently active,&lt;/li&gt;
&lt;li&gt;MUSB_INTRRX: indicates which of the interrupts for TX endpoints are
currently active.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that musb_readb() is used to read 8-bit registers at most, while
musb_readw() allows us to read at most 16-bit registers. There are
other functions that can be used depending on the size of your device
registers. See musb_io.h for more information.&lt;/p&gt;
&lt;p&gt;Instruction on line 18 is another quirk specific to the JZ4740 USB
device controller, which will be discussed later in &lt;a class="reference internal" href="#chapter-5-device-quirks"&gt;Chapter 5&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The glue layer still needs to register the IRQ handler though.
Remember the instruction on line 14 of the init function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_musb_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;isr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_interrupt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;!-- DONE:
- explain how we setup the IRQ handler --&gt;
&lt;p&gt;This instruction sets a pointer to the glue layer IRQ handler
function, in order for the controller hardware to call the handler
back when an IRQ comes from the controller hardware. The interrupt
handler is now implemented and registered.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="chapter-4-device-platform-data"&gt;
&lt;h2&gt;Chapter 4 - Device Platform Data&lt;/h2&gt;
&lt;p&gt;In order to write an MUSB glue layer, you need to have some data
describing the hardware capabilities of your controller hardware,
which is called the platform data.&lt;/p&gt;
&lt;p&gt;Platform data is specific to your hardware, though it may cover a
broad range of devices, and is generally found somewhere in the arch/
directory, depending on your device architecture.&lt;/p&gt;
&lt;p&gt;For instance, platform data for the JZ4740 SoC is found in
arch/mips/jz4740/platform.c. In the platform.c file each device of the
JZ4740 SoC is described through a set of structures.&lt;/p&gt;
&lt;p&gt;Here is the part of arch/mips/jz4740/platform.c that covers the USB
Device Controller (UDC):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;
&lt;span class="normal"&gt;24&lt;/span&gt;
&lt;span class="normal"&gt;25&lt;/span&gt;
&lt;span class="normal"&gt;26&lt;/span&gt;
&lt;span class="normal"&gt;27&lt;/span&gt;
&lt;span class="normal"&gt;28&lt;/span&gt;
&lt;span class="normal"&gt;29&lt;/span&gt;
&lt;span class="normal"&gt;30&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cm"&gt;/* USB Device Controller */&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;platform_device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_udc_xceiv_device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;usb_phy_gen_xceiv&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_udc_resources&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;JZ4740_UDC_BASE_ADDR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;JZ4740_UDC_BASE_ADDR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IORESOURCE_MEM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;JZ4740_IRQ_UDC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;JZ4740_IRQ_UDC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IORESOURCE_IRQ&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;platform_device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_udc_device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;musb-jz4740&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dma_mask&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;jz4740_udc_device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coherent_dma_mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coherent_dma_mask&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DMA_BIT_MASK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_resources&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ARRAY_SIZE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jz4740_udc_resources&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_udc_resources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The jz4740_udc_xceiv_device platform device structure (line 2)
describes the UDC transceiver with a name and id number.&lt;/p&gt;
&lt;p&gt;At the time of this writing, note that &amp;quot;usb_phy_gen_xceiv&amp;quot; is the
specific name to be used for all transceivers that are either built-in
with reference USB IP or autonomous and doesn't require any PHY
programming. You will need to set CONFIG_NOP_USB_XCEIV=y in the kernel
configuration to make use of the corresponding transceiver driver.
The id field could be set to -1 (equivalent to PLATFORM_DEVID_NONE),
-2 (equivalent to PLATFORM_DEVID_AUTO) or start with 0 for the first
device of this kind if we want a specific id number.&lt;/p&gt;
&lt;!-- DONE:
- Go through struct resource jz4740_udc_resources
- Go through struct platform_device jz4740_udc_device --&gt;
&lt;p&gt;The jz4740_udc_resources resource structure (line 7) defines the UDC
registers base addresses.&lt;/p&gt;
&lt;p&gt;The first array (line 9 to 11) defines the UDC registers base memory
addresses: start points to the first register memory address, end
points to the last register memory address and the flags member
defines the type of resource we are dealing with. So IORESOURCE_MEM is
used to define the registers memory addresses.
The second array (line 14 to 17) defines the UDC IRQ registers
addresses. Since there is only one IRQ register available for the
JZ4740 UDC, start and end point at the same address. The
IORESOURCE_IRQ flag tells that we are dealing with IRQ resources, and
the name &amp;quot;mc&amp;quot; is in fact hard-coded in the MUSB core in order for the
controller driver to retrieve this IRQ resource by querying it by its
name.&lt;/p&gt;
&lt;p&gt;Finally, the jz4740_udc_device platform device structure (line 21)
describes the UDC itself.&lt;/p&gt;
&lt;p&gt;The &amp;quot;musb-jz4740&amp;quot; name (line 22) defines the MUSB driver that is used
for this device; remember this is in fact the name that we used in the
jz4740_driver platform driver structure in &lt;a class="reference internal" href="#chapter-2-linux-musb-basics"&gt;Chapter 2&lt;/a&gt;.
The id field (line 23) is set to -1 (equivalent to
PLATFORM_DEVID_NONE) since we do not need an id for the device: the
MUSB controller driver was already set to allocate an automatic id in
&lt;a class="reference internal" href="#chapter-2-linux-musb-basics"&gt;Chapter 2&lt;/a&gt;.
In the dev field we care for DMA related information here. The
dma_mask field (line 25) defines the width of the DMA mask that is
going to be used, and coherent_dma_mask (line 26) has the same purpose
but for the alloc_coherent DMA mappings: in both cases we are using a
32 bits mask.
Then the resource field (line 29) is simply a pointer to the resource
structure defined before, while the num_resources field (line 28)
keeps track of the number of arrays defined in the resource structure
(in this case there were two resource arrays defined before).&lt;/p&gt;
&lt;!-- DONE:
- Go through platform data in jz4740.c --&gt;
&lt;p&gt;With this quick overview of the UDC platform data at the arch/ level
now done, let's get back to the MUSB glue layer specific platform data
in drivers/usb/musb/jz4740.c:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb_hdrc_config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* Silicon does not implement USB OTG. */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;multipoint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* Max EPs scanned, driver will decide which EP can be used. */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_eps&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* RAMbits needed to configure EPs from table */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ram_bits&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fifo_cfg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_fifo_cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fifo_cfg_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ARRAY_SIZE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_fifo_cfg&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb_hdrc_platform_data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_platform_data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_PERIPHERAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;First the glue layer configures some aspects of the controller driver
operation related to the controller hardware specifics. This is done
through the jz4740_musb_config musb_hdrc_config structure.&lt;/p&gt;
&lt;p&gt;Defining the OTG capability of the controller hardware, the multipoint
member (line 3) is set to 0 (equivalent to false) since the JZ4740 UDC
is not OTG compatible.
Then num_eps (line 5) defines the number of USB endpoints of the
controller hardware, including endpoint 0: here we have 3 endpoints +
endpoint 0.
Next is ram_bits (line 7) which is the width of the RAM address bus
for the MUSB controller hardware. This information is needed when the
controller driver cannot automatically configure endpoints by reading
the relevant controller hardware registers. This issue will be
discussed when we get to device quirks in &lt;a class="reference internal" href="#chapter-5-device-quirks"&gt;Chapter 5&lt;/a&gt;.
Last two fields (line 8 and 9) are also about device quirks: fifo_cfg
points to the USB endpoints configuration table and fifo_cfg_size
keeps track of the size of the number of entries in that configuration
table. More on that later in &lt;a class="reference internal" href="#chapter-5-device-quirks"&gt;Chapter 5&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then this configuration is embedded inside jz4740_musb_platform_data
musb_hdrc_platform_data structure (line 11): config is a pointer to
the configuration structure itself, and mode tells the controller
driver if the controller hardware may be used as MUSB_HOST only,
MUSB_PERIPHERAL only or MUSB_OTG which is a dual mode.&lt;/p&gt;
&lt;p&gt;Remember that jz4740_musb_platform_data is then used to convey
platform data information as we have seen in the probe function in
&lt;a class="reference internal" href="#chapter-2-linux-musb-basics"&gt;Chapter 2&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="chapter-5-device-quirks"&gt;
&lt;h2&gt;Chapter 5 - Device Quirks&lt;/h2&gt;
&lt;p&gt;Completing the platform data specific to your device, you may also
need to write some code in the glue layer to work around some
device specific limitations.
These quirks may be due to some hardware bugs, or simply be the result
of an incomplete implementation of the USB On-the-Go specification.&lt;/p&gt;
&lt;p&gt;The JZ4740 UDC exhibits such quirks, some of which we will discuss
here for the sake of insight even though these might not be found in
the controller hardware you are working on.&lt;/p&gt;
&lt;!-- DONE:
- Discuss init() dyn_fifo quirk
- Discuss jz4740_musb_fifo_cfg[] EP config table --&gt;
&lt;p&gt;Let's get back to the init function first:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_musb_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xceiv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;usb_get_phy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USB_PHY_TYPE_USB2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;xceiv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;pr_err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;HS UDC: no transceiver configured&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ENODEV&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* Silicon does not implement ConfigData register.&lt;/span&gt;
&lt;span class="cm"&gt;         * Set dyn_fifo to avoid reading EP config from hardware.&lt;/span&gt;
&lt;span class="cm"&gt;         */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;dyn_fifo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;isr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_interrupt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Instruction on line 12 helps the MUSB controller driver to work around
the fact that the controller hardware is missing registers that are
used for USB endpoints configuration.&lt;/p&gt;
&lt;p&gt;Without these registers, the controller driver is unable to read the
endpoints configuration from the hardware, so we use line 12
instruction to bypass reading the configuration from silicon, and rely
on a hard-coded table that describes the endpoints configuration
instead:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb_fifo_cfg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jz4740_musb_fifo_cfg&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hw_ep_num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FIFO_TX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maxpacket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hw_ep_num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FIFO_RX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maxpacket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hw_ep_num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FIFO_TX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maxpacket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Looking at the configuration table above, we see that each endpoints
is described by three fields: hw_ep_num is the endpoint number, style
is its direction (either FIFO_TX for the controller driver to send
packets in the controller hardware, or FIFO_RX to receive packets from
hardware), and maxpacket defines the maximum size of each data packet
that can be transmitted over that endpoint.
Reading from the table, the controller driver knows that endpoint 1
can be used to send and receive USB data packets of 512 bytes at once
(this is in fact a bulk in/out endpoint), and endpoint 2 can be used
to send data packets of 64 bytes at once (this is in fact an interrupt
endpoint).&lt;/p&gt;
&lt;p&gt;Note that there is no information about endpoint 0 here: that one is
implemented by default in every silicon design, with a predefined
configuration according to the USB specification. For more examples of
endpoint configuration tables, see musb_core.c.&lt;/p&gt;
&lt;!-- DONE:
- Discuss IRQ handler quirk --&gt;
&lt;p&gt;Let's now get back to the interrupt handler function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;
&lt;span class="normal"&gt;24&lt;/span&gt;
&lt;span class="normal"&gt;25&lt;/span&gt;
&lt;span class="normal"&gt;26&lt;/span&gt;
&lt;span class="normal"&gt;27&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;irqreturn_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jz4740_musb_interrupt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;irq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;__hci&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;irqreturn_t&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;retval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IRQ_NONE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;musb&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__hci&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;spin_lock_irqsave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_usb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb_readb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mregs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTRUSB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_tx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb_readw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mregs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTRTX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_rx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb_readw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mregs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTRRX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;         * The controller is gadget only, the state of the host mode IRQ bits is&lt;/span&gt;
&lt;span class="cm"&gt;         * undefined. Mask them to make sure that the musb driver core will&lt;/span&gt;
&lt;span class="cm"&gt;         * never see them set&lt;/span&gt;
&lt;span class="cm"&gt;         */&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_usb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTR_SUSPEND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTR_RESUME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTR_RESET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MUSB_INTR_SOF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_usb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_tx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;int_rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;retval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;musb_interrupt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;spin_unlock_irqrestore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;musb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;retval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Instruction on line 18 above is a way for the controller driver to
work around the fact that some interrupt bits used for USB host mode
operation are missing in the MUSB_INTRUSB register, thus left in an
undefined hardware state, since this MUSB controller hardware is used
in peripheral mode only.
As a consequence, the glue layer masks these missing bits out to avoid
parasite interrupts by doing a logical AND operation between the value
read from MUSB_INTRUSB and the bits that are actually implemented in
the register.&lt;/p&gt;
&lt;p&gt;These are only a couple of the quirks found in the JZ4740 USB device
controller. Some others were directly addressed in the MUSB core since
the fixes were generic enough to provide a better handling of the issues
for others controller hardware eventually.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="chapter-6-conclusion"&gt;
&lt;h2&gt;Chapter 6 - Conclusion&lt;/h2&gt;
&lt;p&gt;Writing a Linux MUSB glue layer should be a more accessible task, as
this documentation tries to show the ins and outs of this exercise.&lt;/p&gt;
&lt;p&gt;The JZ4740 USB device controller being fairly simple, I hope its glue
layer serves as a good example for the curious mind. Used with the
current MUSB glue layers, this documentation should provide enough
guidance to get started; should anything gets out of hand, the
linux-usb mailing list archive is another helpful resource to browse
through.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="chapter-7-acknowledgements"&gt;
&lt;h2&gt;Chapter 7 - Acknowledgements&lt;/h2&gt;
&lt;p&gt;Many thanks to Lars-Peter Clausen and Maarten ter Huurne for answering
my questions while I was writing the JZ4740 glue layer and for helping
me out getting the code in good shape.&lt;/p&gt;
&lt;p&gt;I would also like to thank the Qi-Hardware community at large for its
cheerful guidance and support.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="resources"&gt;
&lt;h2&gt;Resources&lt;/h2&gt;
&lt;p&gt;USB Home Page: &lt;a class="reference external" href="http://www.usb.org"&gt;http://www.usb.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;linux-usb Mailing List Archives: &lt;a class="reference external" href="http://marc.info/?l=linux-usb"&gt;http://marc.info/?l=linux-usb&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;USB On-the-Go Basics: &lt;a class="reference external" href="http://www.maximintegrated.com/app-notes/index.mvp/id/1822"&gt;http://www.maximintegrated.com/app-notes/index.mvp/id/1822&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Writing USB Device Drivers: &lt;a class="reference external" href="https://www.kernel.org/doc/htmldocs/writing_usb_driver/index.html"&gt;https://www.kernel.org/doc/htmldocs/writing_usb_driver/index.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Texas Instruments USB Configuration Wiki Page: &lt;a class="reference external" href="http://processors.wiki.ti.com/index.php/Usbgeneralpage"&gt;http://processors.wiki.ti.com/index.php/Usbgeneralpage&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Analog Devices Blackfin MUSB Configuration: &lt;a class="reference external" href="http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:musb"&gt;http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:musb&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Archives"/><category term="Ben NanoNote"/><category term="Linux kernel"/><category term="Programming"/></entry><entry><title>The Tao Of Programming</title><link href="https://apelete.missene.com/the-tao-of-programming.html" rel="alternate"/><published>2013-12-31T00:00:00+01:00</published><updated>2024-08-15T19:36:11.689418+02:00</updated><author><name>Apelete Seketeli</name></author><id>tag:apelete.missene.com,2013-12-31:/the-tao-of-programming.html</id><summary type="html">&lt;p&gt;Translated by Geoffrey James&lt;/p&gt;
&lt;p&gt;Transcribed by Duke Hillard&lt;/p&gt;
&lt;p&gt;Transmitted by Anupam Trivedi, Sajitha Tampi, and Meghshyam Jagannath&lt;/p&gt;
&lt;p&gt;Re-html-ized and edited by Kragen Sittler&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="table-of-contents"&gt;
&lt;h2&gt;Table Of Contents&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-1-the-silent-void"&gt;The Silent Void&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-2-the-ancient-masters"&gt;The Ancient Masters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-3-design"&gt;Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-4-coding"&gt;Coding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-5-maintenance"&gt;Maintenance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-6-management"&gt;Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-7-corporate-wisdom"&gt;Corporate Wisdom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-8-hardware-and-software"&gt;Hardware and Software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-9-epilogue"&gt;Epilogue&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-1-the-silent-void"&gt;
&lt;h2&gt;Book 1 - The Silent Void&lt;/h2&gt;
&lt;p&gt;Thus spake the …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;Translated by Geoffrey James&lt;/p&gt;
&lt;p&gt;Transcribed by Duke Hillard&lt;/p&gt;
&lt;p&gt;Transmitted by Anupam Trivedi, Sajitha Tampi, and Meghshyam Jagannath&lt;/p&gt;
&lt;p&gt;Re-html-ized and edited by Kragen Sittler&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="table-of-contents"&gt;
&lt;h2&gt;Table Of Contents&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-1-the-silent-void"&gt;The Silent Void&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-2-the-ancient-masters"&gt;The Ancient Masters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-3-design"&gt;Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-4-coding"&gt;Coding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-5-maintenance"&gt;Maintenance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-6-management"&gt;Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-7-corporate-wisdom"&gt;Corporate Wisdom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-8-hardware-and-software"&gt;Hardware and Software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#book-9-epilogue"&gt;Epilogue&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-1-the-silent-void"&gt;
&lt;h2&gt;Book 1 - The Silent Void&lt;/h2&gt;
&lt;p&gt;Thus spake the master programmer:&lt;/p&gt;
&lt;p&gt;“When you have learned to snatch the error code from the trap frame, it will be time for you to leave.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-1"&gt;
&lt;h2&gt;1.1&lt;/h2&gt;
&lt;p&gt;Something mysterious is formed, born in the silent void. Waiting alone and unmoving, it is at once still and yet in constant motion. It is the source of all programs. I do not know its name, so I will call it the Tao of Programming.&lt;/p&gt;
&lt;p&gt;If the Tao is great, then the operating system is great. If the operating system is great, then the compiler is great. If the compiler is great, then the application is great. The user is pleased and there exists harmony in the world.&lt;/p&gt;
&lt;p&gt;The Tao of Programming flows far away and returns on the wind of morning.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-2"&gt;
&lt;h2&gt;1.2&lt;/h2&gt;
&lt;p&gt;The Tao gave birth to machine language. Machine language gave birth to the assembler.&lt;/p&gt;
&lt;p&gt;The assembler gave birth to the compiler. Now there are ten thousand languages.&lt;/p&gt;
&lt;p&gt;Each language has its purpose, however humble. Each language expresses the Yin and Yang of software. Each language has its place within the Tao.&lt;/p&gt;
&lt;p&gt;But do not program in &lt;tt class="docutils literal"&gt;COBOL&lt;/tt&gt; if you can avoid it.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-3"&gt;
&lt;h2&gt;1.3&lt;/h2&gt;
&lt;p&gt;In the beginning was the Tao. The Tao gave birth to Space and Time. Therefore Space and Time are Yin and Yang of programming.&lt;/p&gt;
&lt;p&gt;Programmers that do not comprehend the Tao are always running out of time and space for their programs. Programmers that comprehend the Tao always have enough time and space to accomplish their goals.&lt;/p&gt;
&lt;p&gt;How could it be otherwise?&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-4"&gt;
&lt;h2&gt;1.4&lt;/h2&gt;
&lt;p&gt;The wise programmer is told about Tao and follows it. The average programmer is told about Tao and searches for it. The foolish programmer is told about Tao and laughs at it.&lt;/p&gt;
&lt;p&gt;If it were not for laughter, there would be no Tao.&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;The highest sounds are hardest to hear.&lt;/div&gt;
&lt;div class="line"&gt;Going forward is a way to retreat.&lt;/div&gt;
&lt;div class="line"&gt;Great talent shows itself late in life.&lt;/div&gt;
&lt;div class="line"&gt;Even a perfect program still has bugs.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-2-the-ancient-masters"&gt;
&lt;h2&gt;Book 2 - The Ancient Masters&lt;/h2&gt;
&lt;p&gt;Thus spake the master programmer:&lt;/p&gt;
&lt;p&gt;“After three days without programming, life becomes meaningless.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-5"&gt;
&lt;h2&gt;2.1&lt;/h2&gt;
&lt;p&gt;The programmers of old were mysterious and profound. We cannot fathom their thoughts, so all we do is describe their appearance.&lt;/p&gt;
&lt;p&gt;Aware, like a fox crossing the water. Alert, like a general on the battlefield. Kind, like a hostess greeting her guests. Simple, like uncarved blocks of wood. Opaque, like black pools in darkened caves.&lt;/p&gt;
&lt;p&gt;Who can tell the secrets of their hearts and minds?&lt;/p&gt;
&lt;p&gt;The answer exists only in Tao.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-6"&gt;
&lt;h2&gt;2.2&lt;/h2&gt;
&lt;p&gt;Grand Master Turing once dreamed that he was a machine. When he awoke he exclaimed:&lt;/p&gt;
&lt;blockquote&gt;
“I don't know whether I am Turing dreaming that I am a machine, or a machine dreaming that I am Turing!”&lt;/blockquote&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-7"&gt;
&lt;h2&gt;2.3&lt;/h2&gt;
&lt;p&gt;A programmer from a very large computer company went to a software conference and then returned to report to his manager, saying: “What sort of programmers work for other companies? They behaved badly and were unconcerned with appearances. Their hair was long and unkempt and their clothes were wrinkled and old. They crashed our hospitality suite and they made rude noises during my presentation.”&lt;/p&gt;
&lt;p&gt;The manager said: “I should have never sent you to the conference. Those programmers live beyond the physical world. They consider life absurd, an accidental coincidence. They come and go without knowing limitations. Without a care, they live only for their programs. Why should they bother with social conventions?”&lt;/p&gt;
&lt;p&gt;“They are alive within the Tao.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-8"&gt;
&lt;h2&gt;2.4&lt;/h2&gt;
&lt;p&gt;A novice asked the Master: “Here is a programmer that never designs, documents or tests his programs. Yet all who know him consider him one of the best programmers in the world. Why is this?”&lt;/p&gt;
&lt;p&gt;The Master replies: “That programmer has mastered the Tao. He has gone beyond the need for design; he does not become angry when the system crashes, but accepts the universe without concern. He has gone beyond the need for documentation; he no longer cares if anyone else sees his code. He has gone beyond the need for testing; each of his programs are perfect within themselves, serene and elegant, their purpose self-evident. Truly, he has entered the mystery of Tao.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-3-design"&gt;
&lt;h2&gt;Book 3 - Design&lt;/h2&gt;
&lt;p&gt;Thus spake the master programmer:&lt;/p&gt;
&lt;p&gt;“When the program is being tested, it is too late to make design changes.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-9"&gt;
&lt;h2&gt;3.1&lt;/h2&gt;
&lt;p&gt;There once was a man who went to a computer trade show. Each day as he entered, the man told the guard at the door:&lt;/p&gt;
&lt;blockquote&gt;
“I am a great thief, renowned for my feats of shoplifting. Be forewarned, for this trade show shall not escape unplundered.”&lt;/blockquote&gt;
&lt;p&gt;This speech disturbed the guard greatly, because there were millions of dollars of computer equipment inside, so he watched the man carefully. But the man merely wandered from booth to booth, humming quietly to himself.&lt;/p&gt;
&lt;p&gt;When the man left, the guard took him aside and searched his clothes, but nothing was to be found.&lt;/p&gt;
&lt;p&gt;On the next day of the trade show, the man returned and chided the guard saying: “I escaped with a vast booty yesterday, but today will be even better.” So the guard watched him ever more closely, but to no avail.&lt;/p&gt;
&lt;p&gt;On the final day of the trade show, the guard could restrain his curiosity no longer. “Sir Thief,” he said, “I am so perplexed, I cannot live in peace. Please enlighten me. What is it that you are stealing?”&lt;/p&gt;
&lt;p&gt;The man smiled. “I am stealing ideas,” he said.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-10"&gt;
&lt;h2&gt;3.2&lt;/h2&gt;
&lt;p&gt;There once was a master programmer who wrote unstructured programs. A novice programmer, seeking to imitate him, also began to write unstructured programs. When the novice asked the master to evaluate his progress, the master criticized him for writing unstructured programs, saying, “What is appropriate for the master is not appropriate for the novice. You must understand the Tao before transcending structure.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-11"&gt;
&lt;h2&gt;3.3&lt;/h2&gt;
&lt;p&gt;There was once a programmer who was attached to the court of the warlord of Wu. The warlord asked the programmer: “Which is easier to design: an accounting package or an operating system?”&lt;/p&gt;
&lt;p&gt;“An operating system,” replied the programmer.&lt;/p&gt;
&lt;p&gt;The warlord uttered an exclamation of disbelief. “Surely an accounting package is trivial next to the complexity of an operating system,” he said.&lt;/p&gt;
&lt;p&gt;“Not so,” said the programmer, “when designing an accounting package, the programmer operates as a mediator between people having different ideas: how it must operate, how its reports must appear, and how it must conform to the tax laws. By contrast, an operating system is not limited by outside appearances. When designing an operating system, the programmer seeks the simplest harmony between machine and ideas. This is why an operating system is easier to design.”&lt;/p&gt;
&lt;p&gt;The warlord of Wu nodded and smiled. “That is all good and well, but which is easier to debug?”&lt;/p&gt;
&lt;p&gt;The programmer made no reply.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-12"&gt;
&lt;h2&gt;3.4&lt;/h2&gt;
&lt;p&gt;A manager went to the master programmer and showed him the requirements document for a new application. The manager asked the master: “How long will it take to design this system if I assign five programmers to it?”&lt;/p&gt;
&lt;p&gt;“It will take one year,” said the master promptly.&lt;/p&gt;
&lt;p&gt;“But we need this system immediately or even sooner! How long will it take if I assign ten programmers to it?”&lt;/p&gt;
&lt;p&gt;The master programmer frowned. “In that case, it will take two years.”&lt;/p&gt;
&lt;p&gt;“And what if I assign a hundred programmers to it?”&lt;/p&gt;
&lt;p&gt;The master programmer shrugged. “Then the design will never be completed,” he said.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-4-coding"&gt;
&lt;h2&gt;Book 4 - Coding&lt;/h2&gt;
&lt;p&gt;Thus spake the master programmer:&lt;/p&gt;
&lt;p&gt;“A well-written program is its own heaven; a poorly-written program is its own hell.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-13"&gt;
&lt;h2&gt;4.1&lt;/h2&gt;
&lt;p&gt;A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity.&lt;/p&gt;
&lt;p&gt;A program should follow the ‘Law of Least Astonishment’. What is this law? It is simply that the program should always respond to the user in the way that astonishes him least.&lt;/p&gt;
&lt;p&gt;A program, no matter how complex, should act as a single unit. The program should be directed by the logic within rather than by outward appearances.&lt;/p&gt;
&lt;p&gt;If the program fails in these requirements, it will be in a state of disorder and confusion. The only way to correct this is to rewrite the program.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-14"&gt;
&lt;h2&gt;4.2&lt;/h2&gt;
&lt;p&gt;A novice asked the master: “I have a program that sometime runs and sometimes aborts. I have followed the rules of programming, yet I am totally baffled. What is the reason for this?”&lt;/p&gt;
&lt;p&gt;The master replied: “You are confused because you do not understand Tao. Only a fool expects rational behavior from his fellow humans. Why do you expect it from a machine that humans have constructed? Computers simulate determinism; only Tao is perfect.”&lt;/p&gt;
&lt;p&gt;“The rules of programming are transitory; only Tao is eternal. Therefore you must contemplate Tao before you receive enlightenment.”&lt;/p&gt;
&lt;p&gt;“But how will I know when I have received enlightenment?” asked the novice.&lt;/p&gt;
&lt;p&gt;“Your program will then run correctly,” replied the master.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-15"&gt;
&lt;h2&gt;4.3&lt;/h2&gt;
&lt;p&gt;A master was explaining the nature of Tao of to one of his novices. “The Tao is embodied in all software - regardless of how insignificant,” said the master.&lt;/p&gt;
&lt;p&gt;“Is the Tao in a hand-held calculator?” asked the novice.&lt;/p&gt;
&lt;p&gt;“It is,” came the reply.&lt;/p&gt;
&lt;p&gt;“Is the Tao in a video game?” continued the novice.&lt;/p&gt;
&lt;p&gt;“It is even in a video game,” said the master.&lt;/p&gt;
&lt;p&gt;“And is the Tao in the DOS for a personal computer?”&lt;/p&gt;
&lt;p&gt;The master coughed and shifted his position slightly. “The lesson is over for today,” he said.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-16"&gt;
&lt;h2&gt;4.4&lt;/h2&gt;
&lt;p&gt;Prince Wang's programmer was coding software. His fingers danced upon the keyboard. The program compiled without an error message, and the program ran like a gentle wind.&lt;/p&gt;
&lt;p&gt;“Excellent!” the Prince exclaimed, “Your technique is faultless!”&lt;/p&gt;
&lt;p&gt;“Technique?” said the programmer turning from his terminal, “What I follow is Tao - beyond all techniques! When I first began to program I would see before me the whole problem in one mass. After three years I no longer saw this mass. Instead, I used subroutines. But now I see nothing. My whole being exists in a formless void. My senses are idle. My spirit, free to work without plan, follows its own instinct. In short, my program writes itself. True, sometimes there are difficult problems. I see them coming, I slow down, I watch silently. Then I change a single line of code and the difficulties vanish like puffs of idle smoke. I then compile the program. I sit still and let the joy of the work fill my being. I close my eyes for a moment and then log off.”&lt;/p&gt;
&lt;p&gt;Prince Wang said, “Would that all of my programmers were as wise!”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-5-maintenance"&gt;
&lt;h2&gt;Book 5 - Maintenance&lt;/h2&gt;
&lt;p&gt;Thus spake the master programmer:&lt;/p&gt;
&lt;p&gt;“Though a program be but three lines long, someday it will have to be maintained.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-17"&gt;
&lt;h2&gt;5.1&lt;/h2&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;A well-used door needs no oil on its hinges.&lt;/div&gt;
&lt;div class="line"&gt;A swift-flowing stream does not grow stagnant.&lt;/div&gt;
&lt;div class="line"&gt;Neither sound nor thoughts can travel through a vacuum.&lt;/div&gt;
&lt;div class="line"&gt;Software rots if not used.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;These are great mysteries.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-18"&gt;
&lt;h2&gt;5.2&lt;/h2&gt;
&lt;p&gt;A manager asked a programmer how long it would take him to finish the program on which he was working. “It will be finished tomorrow,” the programmer promptly replied.&lt;/p&gt;
&lt;p&gt;“I think you are being unrealistic,” said the manager, “Truthfully, how long will it take?”&lt;/p&gt;
&lt;p&gt;The programmer thought for a moment. “I have some features that I wish to add. This will take at least two weeks,” he finally said.&lt;/p&gt;
&lt;p&gt;“Even that is too much to expect,” insisted the manager, “I will be satisfied if you simply tell me when the program is complete.”&lt;/p&gt;
&lt;p&gt;The programmer agreed to this.&lt;/p&gt;
&lt;p&gt;Several years later, the manager retired. On the way to his retirement luncheon, he discovered the programmer asleep at his terminal. He had been programming all night.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-19"&gt;
&lt;h2&gt;5.3&lt;/h2&gt;
&lt;p&gt;A novice programmer was once assigned to code a simple financial package.&lt;/p&gt;
&lt;p&gt;The novice worked furiously for many days, but when his master reviewed his program, he discovered that it contained a screen editor, a set of generalized graphics routines, an artificial intelligence interface, but not the slightest mention of anything financial.&lt;/p&gt;
&lt;p&gt;When the master asked about this, the novice became indignant. “Don't be so impatient,” he said, “I'll put in the financial stuff eventually.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-20"&gt;
&lt;h2&gt;5.4&lt;/h2&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Does a good farmer neglect a crop he has planted?&lt;/div&gt;
&lt;div class="line"&gt;Does a good teacher overlook even the most humble student?&lt;/div&gt;
&lt;div class="line"&gt;Does a good father allow a single child to starve?&lt;/div&gt;
&lt;div class="line"&gt;Does a good programmer refuse to maintain his code?&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-6-management"&gt;
&lt;h2&gt;Book 6 - Management&lt;/h2&gt;
&lt;p&gt;Thus spake the master programmer:&lt;/p&gt;
&lt;p&gt;“Let the programmers be many and the managers few - then all will be productive.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-21"&gt;
&lt;h2&gt;6.1&lt;/h2&gt;
&lt;p&gt;When managers hold endless meetings, the programmers write games. When accountants talk of quarterly profits, the development budget is about to be cut. When senior scientists talk blue sky, the clouds are about to roll in.&lt;/p&gt;
&lt;p&gt;Truly, this is not the Tao of Programming.&lt;/p&gt;
&lt;p&gt;When managers make commitments, game programs are ignored. When accountants make long-range plans, harmony and order are about to be restored. When senior scientists address the problems at hand, the problems will soon be solved.&lt;/p&gt;
&lt;p&gt;Truly, this is the Tao of Programming.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-22"&gt;
&lt;h2&gt;6.2&lt;/h2&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Why are programmers non-productive?&lt;/div&gt;
&lt;div class="line"&gt;Because their time is wasted in meetings.&lt;/div&gt;
&lt;/div&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Why are programmers rebellious?&lt;/div&gt;
&lt;div class="line"&gt;Because the management interferes too much.&lt;/div&gt;
&lt;/div&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Why are the programmers resigning one by one?&lt;/div&gt;
&lt;div class="line"&gt;Because they are burnt out.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Having worked for poor management, they no longer value their jobs.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-23"&gt;
&lt;h2&gt;6.3&lt;/h2&gt;
&lt;p&gt;A manager was about to be fired, but a programmer who worked for him invented a new program that became popular and sold well. As a result, the manager retained his job.&lt;/p&gt;
&lt;p&gt;The manager tried to give the programmer a bonus, but the programmer refused it, saying, “I wrote the program because I thought it was an interesting concept, and thus I expect no reward.”&lt;/p&gt;
&lt;p&gt;The manager upon hearing this remarked, “This programmer, though he holds a position of small esteem, understands well the proper duty of an employee. Let us promote him to the exalted position of management consultant!”&lt;/p&gt;
&lt;p&gt;But when told this, the programmer once more refused, saying, “I exist so that I can program. If I were promoted, I would do nothing but waste everyone's time. Can I go now? I have a program that I'm working on.&amp;quot;&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-24"&gt;
&lt;h2&gt;6.4&lt;/h2&gt;
&lt;p&gt;A manager went to his programmers and told them: “As regards to your work hours: you are going to have to come in at nine in the morning and leave at five in the afternoon.” At this, all of them became angry and several resigned on the spot.&lt;/p&gt;
&lt;p&gt;So the manager said: “All right, in that case you may set your own working hours, as long as you finish your projects on schedule.” The programmers, now satisfied, began to come in at noon and work to the wee hours of the morning.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-7-corporate-wisdom"&gt;
&lt;h2&gt;Book 7 - Corporate Wisdom&lt;/h2&gt;
&lt;p&gt;Thus spake the master programmer:&lt;/p&gt;
&lt;p&gt;“You can demonstrate a program for a corporate executive, but you can't make him computer literate.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-25"&gt;
&lt;h2&gt;7.1&lt;/h2&gt;
&lt;p&gt;A novice asked the master: “In the east there is a great tree-structure that men call ‘Corporate Headquarters’. It is bloated out of shape with vice presidents and accountants. It issues a multitude of memos, each saying ‘Go, Hence!’ or ‘Go, Hither!’ and nobody knows what is meant. Every year new names are put onto the branches, but all to no avail. How can such an unnatural entity be?”&lt;/p&gt;
&lt;p&gt;The master replied: “You perceive this immense structure and are disturbed that it has no rational purpose. Can you not take amusement from its endless gyrations? Do you not enjoy the untroubled ease of programming beneath its sheltering branches? Why are you bothered by its uselessness?”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-26"&gt;
&lt;h2&gt;7.2&lt;/h2&gt;
&lt;p&gt;In the east there is a shark which is larger than all other fish. It changes into a bird whose wings are like clouds filling the sky. When this bird moves across the land, it brings a message from Corporate Headquarters. This message it drops into the midst of the programmers, like a seagull making its mark upon the beach. Then the bird mounts on the wind and, with the blue sky at its back, returns home.&lt;/p&gt;
&lt;p&gt;The novice programmer stares in wonder at the bird, for he understands it not. The average programmer dreads the coming of the bird, for he fears its message. The master programmer continues to work at his terminal, for he does not know that the bird has come and gone.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-27"&gt;
&lt;h2&gt;7.3&lt;/h2&gt;
&lt;p&gt;The Magician of the Ivory Tower brought his latest invention for the master programmer to examine. The magician wheeled a large black box into the master's office while the master waited in silence.&lt;/p&gt;
&lt;p&gt;“This is an integrated, distributed, general-purpose workstation,” began the magician, “ergonomically designed with a proprietary operating system, sixth generation languages, and multiple state of the art user interfaces. It took my assistants several hundred man years to construct. Is it not amazing?”&lt;/p&gt;
&lt;p&gt;The master raised his eyebrows slightly. “It is indeed amazing,” he said.&lt;/p&gt;
&lt;p&gt;“Corporate Headquarters has commanded,” continued the magician, “that everyone use this workstation as a platform for new programs. Do you agree to this?”&lt;/p&gt;
&lt;p&gt;“Certainly,” replied the master, “I will have it transported to the data center immediately!” And the magician returned to his tower, well pleased.&lt;/p&gt;
&lt;p&gt;Several days later, a novice wandered into the office of the master programmer and said, “I cannot find the listing for my new program. Do you know where it might be?”&lt;/p&gt;
&lt;p&gt;“Yes,” replied the master, “the listings are stacked on the platform in the data center.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-28"&gt;
&lt;h2&gt;7.4&lt;/h2&gt;
&lt;p&gt;The master programmer moves from program to program without fear. No change in management can harm him. He will not be fired, even if the project is cancelled. Why is this? He is filled with Tao.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-8-hardware-and-software"&gt;
&lt;h2&gt;Book 8 - Hardware and Software&lt;/h2&gt;
&lt;p&gt;Thus spake the master programmer:&lt;/p&gt;
&lt;p&gt;“Without the wind, the grass does not move. Without software, hardware is useless.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-29"&gt;
&lt;h2&gt;8.1&lt;/h2&gt;
&lt;p&gt;A novice asked the master: “I perceive that one computer company is much larger than all others. It towers above its competition like a giant among dwarfs. Any one of its divisions could comprise an entire business. Why is this so?”&lt;/p&gt;
&lt;p&gt;The master replied, “Why do you ask such foolish questions? That company is large because it is large. If it only made hardware, nobody would buy it. If it only made software, nobody would use it. If it only maintained systems, people would treat it like a servant. But because it combines all of these things, people think it one of the gods! By not seeking to strive, it conquers without effort.”&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-30"&gt;
&lt;h2&gt;8.2&lt;/h2&gt;
&lt;p&gt;A master programmer passed a novice programmer one day. The master noted the novice's preoccupation with a hand-held computer game. “Excuse me,” he said, “may I examine it?”&lt;/p&gt;
&lt;p&gt;The novice bolted to attention and handed the device to the master. “I see that the device claims to have three levels of play: Easy, Medium, and Hard,” said the master. “Yet every such device has another level of play, where the device seeks not to conquer the human, nor to be conquered by the human.”&lt;/p&gt;
&lt;p&gt;“Pray, great master,” implored the novice, “how does one find this mysterious setting?”&lt;/p&gt;
&lt;p&gt;The master dropped the device to the ground and crushed it underfoot. And suddenly the novice was enlightened.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-31"&gt;
&lt;h2&gt;8.3&lt;/h2&gt;
&lt;p&gt;There was once a programmer who worked upon microprocessors. “Look at how well off I am here,” he said to a mainframe programmer who came to visit, “I have my own operating system and file storage device. I do not have to share my resources with anyone. The software is self-consistent and easy-to-use. Why do you not quit your present job and join me here?”&lt;/p&gt;
&lt;p&gt;The mainframe programmer then began to describe his system to his friend, saying “The mainframe sits like an ancient sage meditating in the midst of the data center. Its disk drives lie end-to-end like a great ocean of machinery. The software is as multifaceted as a diamond, and as convoluted as a primeval jungle. The programs, each unique, move through the system like a swift-flowing river. That is why I am happy where I am.”&lt;/p&gt;
&lt;p&gt;The microcomputer programmer, upon hearing this, fell silent. But the two programmers remained friends until the end of their days.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="section-32"&gt;
&lt;h2&gt;8.4&lt;/h2&gt;
&lt;p&gt;Hardware met Software on the road to Changtse. Software said: “You are Yin and I am Yang. If we travel together we will become famous and earn vast sums of money.” And so the set forth together, thinking to conquer the world.&lt;/p&gt;
&lt;p&gt;Presently they met Firmware, who was dressed in tattered rags and hobbled along propped on a thorny stick. Firmware said to them: “The Tao lies beyond Yin and Yang. It is silent and still as a pool of water. It does not seek fame, therefore nobody knows its presence. It does not seek fortune, for it is complete within itself. It exists beyond space and time.”&lt;/p&gt;
&lt;p&gt;Software and Hardware, ashamed, returned to their homes.&lt;/p&gt;
&lt;/div&gt;
&lt;hr class="docutils" /&gt;
&lt;div class="section" id="book-9-epilogue"&gt;
&lt;h2&gt;Book 9 - Epilogue&lt;/h2&gt;
&lt;p&gt;Thus spake the master programmer:&lt;/p&gt;
&lt;p&gt;“It is time for you to leave.”&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;/div&gt;
</content><category term="Hacking &amp; Tao"/><category term="Programming"/><category term="Tao"/></entry></feed>