<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Open-Source on The Dark Programmer&#39;s Tome of Secrets</title>
        <link>https://blog.devcouncil.org/tags/open-source/</link>
        <description>Recent content in Open-Source on The Dark Programmer&#39;s Tome of Secrets</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Mon, 28 Aug 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.devcouncil.org/tags/open-source/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Reverse engineering a mouse configurator</title>
        <link>https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/</link>
        <pubDate>Mon, 28 Aug 2023 00:00:00 +0000</pubDate>
        
        <guid>https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/</guid>
        <description>&lt;img src="https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/thumbnail.png" alt="Featured image of post Reverse engineering a mouse configurator" /&gt;&lt;h1 id=&#34;preamble-the-problem&#34;&gt;Preamble: The problem
&lt;/h1&gt;&lt;p&gt;Once upon a time I had a mouse. This little mouse had five buttons. The typical three, plus a forward and backward on the side. It was nothing fancy, but it got me hooked on mice with additional buttons. There&amp;rsquo;s something very satisfying about moving through your browser history with a single button that I could not relinquish. After this mouse broke seven years ago, in 2016, I bought a brand new Mars Gaming MM4 18-button mouse. It has a nice 12-button keypad on the side, which can be configured with a propietary tool for Windows.&lt;/p&gt;
&lt;p&gt;I was in university at the time, and Microsoft gave us free Windows keys through the Inspire program. I was already a Linux fanboy, but I had to keep Windows installed to run some programs that were necessary for my university, such as Solidworks, so I put up with this mouse configurator for the time being.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/mm4-config.png&#34;
	width=&#34;801&#34;
	height=&#34;638&#34;
	srcset=&#34;https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/mm4-config_hu_1cefdc7c2487769.png 480w, https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/mm4-config_hu_10b0ab528f988e75.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;The propietary mouse configurator that is used to customize the Mars Gaming MM4 mouse&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;125&#34;
		data-flex-basis=&#34;301px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;After I was done with university, I chose to nuke the Windows partition, which left me with no way of modifying the button mapping or changing the DPI resolution profiles. I tried running the configurator through Wine, but it did not work. It would boot, but it would refuse to communicate with the mouse. I then did the only sensible choice and decided to reverse engineer the configurator tool, or more specifically, the USB communication protocol.&lt;/p&gt;
&lt;h1 id=&#34;reverse-engineering-the-communication-protocol&#34;&gt;Reverse engineering the communication protocol
&lt;/h1&gt;&lt;p&gt;To be able to reverse engineer the communication protocol that the mouse uses, I would firstly need an easy way of intercepting and processing the communication between the computer and the mouse. This proved easy, since Wireshark, our beloved network packet sniffer, can be used to intercept USB communications&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. I then spent a couple of days using the configurator, tweaking a single parameter, capturing the USB output and analyzing it to find how that tweak was encoded in the wire.&lt;/p&gt;
&lt;p&gt;The mouse configurator seemed to be sending and receiving a dozen or so packets to and from the mouse. For each of the tweaks I made, I saved the packets into a pcap file with the data before and after the tweak. To convert the pcap files into a more manageable file format I wrote a small script in python. This scirpt uses the &lt;code&gt;pyshark&lt;/code&gt; library to open the files, extract the info I wanted and write it out as a plain csv, with the binary data displayed as hexadecimal. I then loaded these csv files into Libreoffice Calc for further processing.&lt;/p&gt;
&lt;p&gt;Having the data before and after the tweak allowed me to very easily see the differences that resulted in the tweak being applied. It was a matter of a game &amp;ldquo;Find the differences&amp;rdquo;, only I have a computer to find them for me. Any information I uncovered from this analysis I wrote down into Ghidra, which has a convenient Data Type Manager which lets you define data types, their structure, size and add explanatory comments to them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/ghidra-packet.png&#34;
	width=&#34;568&#34;
	height=&#34;701&#34;
	srcset=&#34;https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/ghidra-packet_hu_62fc87fb1a2b369e.png 480w, https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/ghidra-packet_hu_75d3d36f0efae9f1.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;The packet that assigns actions to each of the buttons of the mouse, as seen in Ghidra&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;81&#34;
		data-flex-basis=&#34;194px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;With this same procedure I managed to reverse engineer around 75% of all the data being sent, and almost all of the exposed features on the configurator tool, with the exception of complex macros&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. I was satisfied with the work I had put in, but all of this would be in vain if I didn&amp;rsquo;t use it to create my own configuration tool.&lt;/p&gt;
&lt;h1 id=&#34;implementing-a-new-driver-in-ratbag&#34;&gt;Implementing a new driver in ratbag
&lt;/h1&gt;&lt;p&gt;I don&amp;rsquo;t need to say this, but creating your own configuration tool from scratch is a very hard task. That&amp;rsquo;s why I chose to implement my findings into the &lt;a class=&#34;link&#34; href=&#34;https://github.com/libratbag/libratbag&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ratbag&lt;/a&gt; project. Ratbag, plus its frontend &lt;a class=&#34;link&#34; href=&#34;https://github.com/libratbag/piper&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Piper&lt;/a&gt;, are MIT/GPLv2 licensed tools for configuring input devices, chiefly mice. They are, as far as I know, the predilect tool for this kind of task in Linux.&lt;/p&gt;
&lt;p&gt;Figuring my way around the repositories took a couple of days, but seeing how other drivers were implemented helped significantly. Implementing a new driver is a matter of implementing two main components: The &lt;code&gt;probe&lt;/code&gt; component, which obtains the current running configuration of the mouse, and the &lt;code&gt;commit&lt;/code&gt; component, which applies the configuration to the mouse. Implementing the &lt;code&gt;commit&lt;/code&gt; component proved easy, since I simply had to replicate the behavior that I previously reverse engineered. I even made it more efficient by not commiting configuration that hasn&amp;rsquo;t been changed, which the propietary tool does not do.&lt;/p&gt;
&lt;p&gt;I then went ahead implementing the &lt;code&gt;probe&lt;/code&gt; component. There is only a slight problem here. The propietary mouse configurator hardly does any probing. It only probes the device id, likely to confirm that it&amp;rsquo;s a supported device. It does not probe the current configuration of the mouse, such as buttons, LEDs and DPI resolutions. The configuration that shows up when the tool is launched is the one that is saved to disk on the host machine.&lt;/p&gt;
&lt;p&gt;It didn&amp;rsquo;t take long while messing around to adapt the protocol to add this new feature. I analyzed the packet that probes the device id and identified the section that allowed for reading values from the mouse. Luckily, the same technique can be applied to the rest of the configurable values so that they can be read.&lt;/p&gt;
&lt;p&gt;In parallel, I was also doing some changes in the Piper project. I needed to create an svg that resembled the mouse that would serve as the UI. Interestingly, Piper doesn&amp;rsquo;t use svg merely for display. It uses specific attributes to identify the location where to put clickable buttons on the UI, or layers to choose which leads to show on each screen, and which ones to highlight on mouse hover.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/piper-mm4.png&#34;
	width=&#34;1008&#34;
	height=&#34;646&#34;
	srcset=&#34;https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/piper-mm4_hu_9a449c99a36ba5dd.png 480w, https://blog.devcouncil.org/posts/mouse-configurator-reverse-engineering/piper-mm4_hu_edc686d8f4d788f1.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;The Mars Gaming MM4 mouse as it appears in Piper&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;156&#34;
		data-flex-basis=&#34;374px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;After I successfully implemented all of the features I considered necessary, I decided to open PRs to &lt;a class=&#34;link&#34; href=&#34;https://github.com/libratbag/piper/pull/692&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Piper&lt;/a&gt; and &lt;a class=&#34;link&#34; href=&#34;https://github.com/libratbag/libratbag/pull/1364&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;libratbag&lt;/a&gt;. After a protracted (by me) review process, both PRs were successfully merged, and will be available in the following release, likely to be v0.18.&lt;/p&gt;
&lt;h1 id=&#34;final-thoughts&#34;&gt;Final thoughts
&lt;/h1&gt;&lt;p&gt;Even though this project was a success, I feel a slight bittersweet aftertaste. I successfully managed to implement everything that I wanted, but what is the likelihood that someone will be using this 8 year-old mouse nowadays, and on linux on top of that? Even I myself don&amp;rsquo;t use the tool that often.&lt;/p&gt;
&lt;p&gt;I am at least glad to be able to have a free and open implementation of the protocol for posterity&amp;rsquo;s sake. At the very least, I hope this post encourages anyone to try the same for their own mice or any other device, either with the specific goal of re-implementing the configuration protocol, or simply exploring the possibilities that the USB protocol can offer.&lt;/p&gt;
&lt;p&gt;And finally, this is a great example as to how free software benefits everyone. I benefit because I can run and modify the program without any restrictions. The project benefits from the contributions, and other users benefit from the collaboration and implementation of new features. This is just a small part of why I love free software.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;The Wireshark USB dissector seems to not be fully implemented. In particular, the USBHID component does not seem to be parsing the GET_REPORT Response, so the response data does not get dissected and displayed neatly. Given this, I attempted to implement my own dissector that would parse the responses into a proper USBHID response packet. I got fairly deep into implementing this, but the usefulness was dwarfed by the effort of implementing and using it, so I did not proceed any further.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;I intentionally chose to forgo reverse engineering the macros. I had never used them, nor was planning to, and it would have added a significant amount of additional work to this process.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
        </item>
        
    </channel>
</rss>
