<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Arbel Shoham on Medium]]></title>
        <description><![CDATA[Stories by Arbel Shoham on Medium]]></description>
        <link>https://medium.com/@arbels?source=rss-63882ee0c5e1------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*caOdh6zDxh1XWAlr</url>
            <title>Stories by Arbel Shoham on Medium</title>
            <link>https://medium.com/@arbels?source=rss-63882ee0c5e1------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 24 May 2026 02:24:47 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@arbels/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Remote Physical Input Device on Linux based devices]]></title>
            <link>https://medium.com/@arbels/remote-physical-input-device-on-linux-based-devices-bdda99004ec4?source=rss-63882ee0c5e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/bdda99004ec4</guid>
            <category><![CDATA[virtual-keyboard]]></category>
            <category><![CDATA[raspberry-pi]]></category>
            <category><![CDATA[embedded-linux]]></category>
            <dc:creator><![CDATA[Arbel Shoham]]></dc:creator>
            <pubDate>Mon, 21 Feb 2022 04:49:53 GMT</pubDate>
            <atom:updated>2022-02-21T05:07:49.657Z</atom:updated>
            <content:encoded><![CDATA[<p>Sometimes you have a setup that has a component running Linux or its derivatives (Android for example) and you would like to give it some user input. If this setup is embedded rather than PC you might find it difficult to use regular input devices such as a keyboard or a mouse, perhaps you don’t have any physical connectors or the device is enclosed in a casing or even just far away from you.</p><p>Take note that sometimes you’ll have a headless system and so remote desktop solutions like VNC won’t work, an ssh approach might mitigate some of the problem, but if you have a process running you won’t be able to access its <em>stdin</em> just your ssh shell’s <em>stdin</em>.</p><p>One solution to that problem could be to create a custom input device driver to use on your system that would receive the data in some other way, that is a good solution although a bit complicated. The developers of the Linux kernel gave us a simpler way than writing our own driver, and from userspace. They have created a special module that allows us to do just that and its called <strong><em>/dev/uinput</em></strong>. <em>uinput </em>is a kernel module that makes it possible to emulate input devices from userspace.</p><p>Some possible use cases:</p><ol><li>You would like to remotely control the navigation of a device (drone/car).</li><li>You have a CPU running Linux inside your system you can’t reach and you want to give it input directly.</li><li>You want to create a remote controller for your Android based media streamer.</li><li>Your system has a custom set of buttons and keys and you would like to develop its software on a PC with standard input and deploy it as is to the target.</li><li>You are an Android app developer or QA and want to create and recreate frequent usage scenarios and run it automatically on the device.</li><li>You want to duplicate one input to several devices that are connected in some way.</li></ol><p>A virtual custom input device will work for all these cases, but how to do it? the documentation for the uinput module in kernel.org states that: B<em>y writing to /dev/uinput (or /dev/input/uinput) device, a process can create a virtual input device with specific capabilities. Once this virtual device is created, the process can send events through it, that will be delivered to userspace and in-kernel consumers.</em></p><p>All the information you need can be found in <a href="https://www.kernel.org/doc/html/v4.12/input/">The Linux Input Documentation</a>, I will mention here a few basics for you to get started, all the code I show including a wrapper class and a tester script can be found in this <a href="https://github.com/arbelsh/virtual-input-device"><strong>repo</strong></a>. The process of building this kind of virtual input device is made of a few steps:</p><p>First you need to open a file descriptor to the module:</p><blockquote>m_fd = open(“<strong>/dev/uinput</strong>”, O_WRONLY | O_NONBLOCK);</blockquote><p>After that comes the stage of configuring and creating the device using several ioctls, first you’ll setup the type of events the device can create, you will probably use one or more of the following:</p><ul><li>EV_KEY — for key press events (like a keyboard)</li><li>EV_REL — for relative movement input (like a mouse)</li><li>EV_ABS — for absolute location events (like a touch screen)</li></ul><blockquote>ioctl(m_fd, <strong>UI_SET_EVBIT</strong>, <strong>EV_KEY</strong>);</blockquote><p>Second is registering the keys you want the device to be able to emulate. all key codes can be found in the <a href="https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h">input-event-codes.h</a> header file</p><blockquote>for (int i = 0; i &lt; sizeof(m_keys)/sizeof(m_keys[0]); i++)<br>{<br> ioctl(m_fd, <strong>UI_SET_KEYBIT</strong>, m_keys[i]); // register all wanted keys<br>}</blockquote><p>Third comes some general information such as vendor and bus type and the device creation itself</p><blockquote>memset(&amp;usetup, 0x0, sizeof(usetup));<br> usetup.id.bustype = <strong>BUS_USB</strong>;<br> usetup.id.vendor = 0x1209; // Generic vendor<br> usetup.id.product = 0x5678;<br> strcpy(usetup.name, m_name);<br> ioctl(m_fd, <strong>UI_DEV_SETUP</strong>, &amp;usetup); // setup the device<br> ioctl(m_fd, <strong>UI_DEV_CREATE</strong>); // create the device</blockquote><p>The last part is the generation of an event, a value of 1 means pressed and 0 means released</p><blockquote>Emit(int type, int code, int val)<br>{<br> struct input_event ie;<br> ie.type = type;<br> ie.code = code;<br> ie.value = val;<br> /* timestamp values below are ignored */<br> ie.time.tv_sec = 0;<br> ie.time.tv_usec = 0;<br> write(m_fd, &amp;ie, sizeof(ie));<br>}</blockquote><blockquote>Emit(EV_KEY, code, 1);<br>Emit(EV_KEY, code, 0);</blockquote><p>to finalize and sync the input and actually send all the events a sync event is generated</p><blockquote>Emit(EV_SYN, SYN_REPORT, 0);</blockquote><p>I made a small POC using a Raspberry Pi + Screen, a laptop and a Wi-Fi connection, all sources can be found <a href="https://github.com/arbelsh/virtual-input-device"><strong>here</strong></a>.</p><p>The Raspberry Pi is connected to a screen and to a Wi-Fi network (no keyboard), the PC is connected to the same Wi-Fi network.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*G922A3w5sMgdhw05GF0ZWg.png" /><figcaption>the POC setup illustration</figcaption></figure><p>On the Raspberry Pi I ran a small app that creates a virtual keyboard with a set of keys and listens to a UDP port to receive instructions for keys pressed and creates input accordingly, for some relevant keys I implemented a toggle mechanism.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/709/1*leCynWiWKj8oXDj1PgqCxg.png" /><figcaption>creating the virtual input device</figcaption></figure><p>On the PC I wrote a python script that sends instructions using a UDP client. The instructions are encoded as ASCII characters which will be parsed on the target. Lowercase letters and whitespaces as their values and uppercase letters for special keys.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/328/1*fyFBfX5gwkimDQ8LCJbHxQ.png" /><figcaption>partial mapping of the ‘special’ keys</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/799/1*wa5TBs1x5cenMDnJKGxWnA.png" /><figcaption>the controller script on the PC</figcaption></figure><p>Finally, the end result is a terminal console opening, an arcade game (<a href="https://en.wikipedia.org/wiki/Dangerous_Dave"><em>Dangerous Dave</em></a>) being run via dosbox and a gameplay of the first level. I captured the screen output of the Raspberry Pi in the next video:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FscpVEFGI8HY%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DscpVEFGI8HY&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FscpVEFGI8HY%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/b9e26991b4142d46619762b5d9e39d40/href">https://medium.com/media/b9e26991b4142d46619762b5d9e39d40/href</a></iframe><p>A word of warning - in this POC I focused on functionality, it is in no way a good idea to use this clear-text, no authentication, direct access protocol on a real system for obvious security reasons, a real system should implement a more secure credential based protocol.</p><p>Notes:</p><ol><li>root privileges are required to access /dev/uinput.</li><li>I recommend reading “<strong>The Linux Input Documentation</strong>” at <a href="https://www.kernel.org/doc/html/v4.12/input/index.html">https://www.kernel.org/doc/html/v4.12/input/index.html</a>, specifically the section on the uinput module.</li><li>There is a wrapper library that provides interfaces to create uinput devices called <a href="https://www.freedesktop.org/software/libevdev/doc/latest/"><strong>libevdev</strong></a>, it’s worth mentioning as it can help implement some of the functionality shown above.</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bdda99004ec4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Physical memory access for embedded developers using Linux — a beginner’s guide]]></title>
            <link>https://medium.com/@arbels/physical-memory-access-for-embedded-developers-using-linux-a-beginners-guide-f3acd271c7d2?source=rss-63882ee0c5e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/f3acd271c7d2</guid>
            <category><![CDATA[embedded]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[access-memory]]></category>
            <dc:creator><![CDATA[Arbel Shoham]]></dc:creator>
            <pubDate>Sun, 19 Dec 2021 05:01:29 GMT</pubDate>
            <atom:updated>2021-12-19T05:01:29.919Z</atom:updated>
            <content:encoded><![CDATA[<h3>Physical memory access for embedded developers using Linux — a beginner’s guide</h3><p>As an embedded developer, a hardware, firmware, FPGA or software engineer you have probably found yourself using Linux to some extent in your system. Many vendors use Linux in their SOCs, SOMs and platforms. Xilinx, Nvidia, TI, RaspberryPi and BeagleBoard to name a few.</p><p>When working on embedded systems it is common for software to interact with hardware elements and to need access to physical memory (memory blocks, registers, PCI mapped regions etc.).</p><p>Some possible use cases:</p><ol><li>You are working on a SOC that has some capabilities that can be controlled through registers.</li><li>You have a system with two processing units connected using PCIe bus and you want to transfer data between them using the PCI mapped regions.</li><li>You are working on a SOC with an FPGA and want to share a buffer between the CPU and the FPGA. Decode a sound sample using a vocoder and pass to the FPGA to calculate the FFT for example.</li><li>You have multiple register values presets on files in the filesystem and you want to load and switch between them on runtime.</li></ol><p>In the Linux operating system the virtual memory is divided to two regions — Kernel space and User space. Kernel space is where the kernel (the core of the operating system) runs and provides services, User space is where all user processes (processes that are not part of the operating system) run. In Kernel space it is possible to access physical addresses, but writing kernel code requires a bit more experience with C and operating systems, furthermore, since the Linux kernel is written solely in C you will be limited to that language only.</p><p>Fortunately for us, Linux has a mechanism to allow memory access from User space using device drivers.</p><p>We have a few options, the first is accessing a memory address from CLI. If we want to read or write an integer value at a specific address we can use a utility called <strong><em>devmem</em></strong>, it is available as part of the busybox software suite. This option is also useful in shell scripting.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/644/1*PsocHZb4jPzq0YdWGLrQfg.png" /><figcaption>usage example for devmem</figcaption></figure><p>But sometimes this isn’t enough, if we need to access a bigger chunk of memory or we want to control and integrate the memory access into our process, we need another option, a device driver called <strong><em>/dev/mem</em></strong>, it is a character device file that is an image of the main memory, byte addresses in <strong><em>mem </em></strong>are interpreted as physical memory addresses. What we need to do is map these addresses and then use them to access the physicals memory addresses.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BB3CFxntTQFjNQgD0ePXcg.png" /><figcaption>usage example for mapping /dev/mem addresses using C</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c997JHq_J57J7nvFuSCstQ.png" /><figcaption>usage example for mapping /dev/mem addresses using Python</figcaption></figure><p>We get the requested offset and size of the memory we want to access, we calculate the nearest memory page aligned address, open the memory device driver and then map the memory using mmap() to get a pointer to a R/W memory block with the requested size.</p><p>As an example of using this method I used my Raspberry Pi 4 that has a timer mechanism (see pg. 157 <a href="https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf"><strong>here</strong></a>) that can be set and read using registers, I load the value to 8000, start the timer, sample it 3 times to show changes and then stop the timer and sample 3 times again to see stable values.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/880/1*xfVkd4L-jRC0uOZPFdnAtg.png" /><figcaption>example code</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/502/1*aTQd2ZcRvHho6zcxWGu_4Q.png" /><figcaption>output of example</figcaption></figure><p>The code for the example in C can be found <a href="https://github.com/arbelsh/devmem_examples/blob/main/devmem_example.c"><strong>here</strong></a> and in Python <a href="https://github.com/arbelsh/devmem_examples/blob/main/devmem_example.py"><strong>here</strong></a>.</p><p>Notes:</p><ol><li>root privileges are required to access /dev/mem.</li><li>I recommend reading the <a href="https://man7.org/linux/man-pages/man4/mem.4.html"><strong>mem</strong></a> and <a href="https://man7.org/linux/man-pages/man2/mmap.2.html"><strong>mmap</strong></a> man pages for better understanding of the mapping.</li><li>if you are having problems accessing some memory regions a possible cause can be that a kernel configuration option that limits access called <strong>CONFIG_STRICT_DEVMEM</strong> is set, you can check your kernel config options to make sure.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/577/1*MOSbBKM-6eOnHdtKaTNBOg.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f3acd271c7d2" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>