Tuesday, April 21, 2015

Audacious plugin for opening folder where files are located

I've been using Winamp for a long time. With a stripped-down configuration and the 2.x interface it is perfect. It supports a lot of formats, plugins and a playlist. With a nice skin it looks good, but takes up very little screen space and resources. I'm used to playing files from folders, and not using any sort of database.

Audacious seems to be the best replacement for Winamp in Linux these days. Its default interface is too big and plain, but it supports Winamp 2.x skins. It also uses plugins to implement various functionality and has an even better plugin API than Winamp.

There didn't seem to be any equivalent of the Winamp "Find File on Disk" plugin, so I created one. This gist contains the source code. To use it, right click on a file in the playlist, go into the "Services" sub-menu and select "Open File Location". You can also select multiple files in the playlist, and they will all be selected in the file manager.

Right now the plugin is written to use the KDE Dolphin file manager, which offers the nice --select flag. I'm not sure how to make this automatically work well with any file manager.

Zooming out in Google Maps and Earth without multitouch

The Android versions of Google Maps and Google Earth are optimized for multi-touch. Double clicking zooms in a set amount, but the way to zoom out with a mouse isn't obvious.

To zoom in or out, double click, but don't release the second click. Keep holding the button and drag the mouse up or down to zoom in or out.

Getting iPod hard drive SMART data via iPodLinux

Hard drives found in iPods generally support SMART. It is useful for checking drive health and running tests. The flash-based diagnostic mode reports only a few of the attributes. Rockbox lacks support for USB mass storage features which would allow programs running on a computer to use iPod hard drive SMART functions. I believe the original firmware's disk mode and the emergency disk mode in flash also lack this support.

Fortunately, there's iPodLinux. With some changes it's possible to cross-compile smartmontools for iPodLinux and run it there. Here's a link to the modified smartmontools-6.1 source with the smartctl binary inside. I did this quickly a while ago. I'm sure it's possible to port smartmontools more elegantly, but this works.

I find iPodLinux text input annoyingly inefficient, so I prepared three text files with these common commands:

smartctl -d ata -a /dev/hda > sao
smartctl -d ata -t long /dev/hda
smartctl -d ata -t short /dev/hda


You must specify -d ata to tell smartctl what type of interface to use. I'm sure it's possible to improve the port to remove that requirement.

Wednesday, April 08, 2015

Porting Rockbox to the RCA RC3000A digital boombox

This is an old post that I didn't get around to completing, and kept as a draft. It talks about how I ported Rockbox to the RCA RC3000A digital boombox. Code is available on GitHub.

Summary

First I opened it up and noted the chips inside. Some already have Rockbox drivers. Then, I figured out how to use USB boot mode to run code using tcctool with slight modifications. I used code to dump the firmware, outputting data via a GPIO pin and reading it via the sound card. Then I did some reverse engineering, figured out various functionality, got a Rockbox bootloader running, got Rockbox running and finally made playback work.

The LCD

First, I wanted a better form of feedback than GPIO pin toggling, so I figured out the LCD. The LCD command and data writing routines can be reached by following subroutine calls from a function that displays strings on the LCD. Then, other functions can be identified which use these functions to do stuff with the LCD. The initialization sequence was interesting. Instead of writing register indexes and then writing data to those registers, some commands have a command number in the high bits and data in the lower bits. I identified the controller by searching through Rockbox LCD driver files for | (which is bitwise or in C). The lcd-archos-bitmap.c driver for the graphical LCD on old Archos devices seemed like a match, so the LCD controller is probably a SSD1815. However, the initialization routine uses different values because the LCD panel is different, and it's important to use those values.

The call to the LCD initialization routine was surrounded by other interesting and relevant code. Just before the initialization, a call to a long function set the TCC760 chip select register for access to the LCD. Instead of trying to understand the function, I simply executed it in ARMSim to get the value. There was also a nearby GPIO call which controls the backlight.

Now it was possible to execute some code and write to the LCD. I thought building even a Rockbox bootloader would be difficult, so I just used a modified lcd-archos-bitmap.c file. This worked, but there was nothing interesting to display. I also verified that the nearby GPIO controlled the backlight. This was tricky, because although the CPU and LCD can run from USB power only, the backlight requires external power.

Building a Rockbox bootloader

This success made me want to try running more of Rockbox. I first decided to build a bootloader, because it uses only selected components of Rockbox. The Rockbox Wiki provides some basic information about how to create a new target. I started off by copying files from the Sansa C100, which uses the related Telechips TCC770 CPU. There were plenty of things to edit and rename, but it was all fairly straightforward, and error messages can serve as a guide showing what needs to be done.

Uploading code to SDRAM

The resulting bootloader was too big for loading in TCC760 internal SRAM, so I needed to use DRAM. Unlike with later chips, USB boot mode doesn't provide a way to set the SDCFG register. So, I used a small bit of assembler code to set SDCFG and then jump back to 0 to restart USB boot mode and enable uploading of a longer program to SDRAM. It was easy to get the bootloader running, but timer interrupts took a bit more work. The TCC760 is similar to TCC770, but there are some key differences with some peripheral register bits.

Figuring out the buttons

The bootloader allowed viewing of GPIO and ADC values which helped me figure out the buttons and some other values. The power/play/pause button is connected to its own GPIO pin, but all the other buttons are connected to one pin, with each connecting it to ground via a different value resistor. This means the ADC must be used to read these buttons. I ended up finding the original firmware routine which reads buttons and using its thresholds between different buttons. I suppose that's better than using measured values, because the measured values are affected by resistor tolerances.

SD card access

The RC3000A has 512MB of internal NAND flash storage, and an SD card. I chose to first use the SD card, because that seems safer. When I viewed GPIO values, I found pins for SD card write protect and SD card detection. I used these to find the SD card code. ARM code typically loads a base address into a register and then accesses a memory mapped peripheral register using that register plus an offset encoded into an instruction. In this case, 0x80000000 is always loaded into the register, so the offsets are predictable and they can be used to search disassembled code for GPIO access with few false matches. There is one unfortunate complication though. All the code I've seen makes the GPIO port obvious, but some uses a value loaded from RAM to define the bit.

I assumed that the SD card uses bit banging because there is no SD controller and USB access to the card is ridiculously slow. I did find bit banging code, but actually the SD card is hooked up to GSIO0, and there is also code for that. I chose to initially use bit banging code, because it is simpler to be sure I'm doing it correctly. GSIO could have left me wondering if the problem was the way I'm using GSIO or the interface to the SD card.

SD card bit bang SPI interface code can be used to add SD cards to routers, and source is available there. However, I chose to start with code from within Rockbox, from the Archos Ondio MMC card driver. Its structure more closely matches my intended final structure, with GSIO and hopefully also DMA.

After learning about the SD card protocol and commands, I first worked on getting initialize_card() working. At first this seemed futile, but then I added the initial synchronizing code sending 0xFF bytes with chip select not asserted and it worked. Then I just had an endianness issue in card_extract_bits() and after that the function succeeded. Then it was simple to read a sector.

Building Rockbox, adding functionality, and getting sound

(Post was interrupted here and continued much later.)

Once SD card reading was available and mountable, it seemed like a good time to run a full build of Rockbox. Since this includes files and functionality not compiled into the bootloader, some work was needed to get it to compile. Then it was time to add more functionality.

First I added I2C support, testing it using the E8564 RTC chip, which Rockbox already supports. The RC3000A uses purely software based bit-banging I2C, although the TCC760 chip does contain an I2C controller. 

I wanted to first set up the CODEC for FM radio playback, which should be simpler than music playback. At first I thought I could use the CS42L55 code present in Rockbox, but the CS42L51 is significantly different, so I ended up creating a new driver using parts of the Linux driver. I got the radio working using the pre-existing TEA5767 driver. Only the headphone jack was usable, because the amplifier driving the speakers was off.

Then it was time to do various tweaks to CODEC and I2S configuration and make playback work. However, the result was interrupted playback, because the device was too slow. I enabled the CPU caches, and started using GSIO for SD card access, and sped up the SD clock. Finally, I got perfect playback of a FLAC file.

Cleanups, tweaks and optimizations

There was still a lot of optimizing to do. The fast internal RAM in the TCC760 could be used to speed up code. Thumb and INIT_ATTR could free up memory. The SD driver needed more work. DMA could be used for playback.

I spent a lot of time trying to get DMA to work with GSIO for SD card accesses, but it seemed impossible and eventually I gave up. I optimized things the best I could with 16 bit GSIO transfers.

Getting USB to work was interesting, because I had never worked with a USB device before.

There were a lot of features to support. Rockbox includes various LCD settings such as flip and inverse, and a way to display greyscale on an LCD which doesn't officially support it. I also enabled sound bass and treble setting via the codec and backlight PWM fading.

Flashing the bootloader

So far, Rockbox could only be loaded via USB boot. It time to flash a Rockbox bootloader with dual-boot support, allowing for choosing between original firmware and Rockbox. I was a bit anxious because this could brick the device, but there was no real danger because USB boot should allow recovery.

Initially, I was thinking I would create a flash plugin and use it to flash the bootloader. However, I ended up creating a firmware upgrade file and flashing it via the original firmware. My first attempt allowed access to original firmware, but failed to run Rockbox. After adding some short initialization code from the original firmware I could load Rockbox.

The end?

Once I had a working Rockbox port, I stopped working on this. The RCA RC3000A devices are probably quite rare, and I've never encountered anyone else interested in running Rockbox on one. It doesn't even seem like there's any interest in running Rockbox on TCC76X devices. Therefore, I don't think adding this port to Rockbox would benefit anyone.

One thing that still interests me is making use of the OHCI USB host controller on the device. The original firmware supports it but fails badly when accessing a large device because it tries to scan all the files and keep a list in memory. I wonder if there's a good free software embedded USB stack? The SeaBIOS code might be useful, but it is GPL 3 and Rockbox is GPL 2.

I've also thought about adding an ESP8266 module and creating a Rockbox plugin for playing Internet radio. Such a plugin could also be used with other targets with externally accessible serial ports, such as the iPods.

Sunday, April 05, 2015

Where is the iPodLinux kernel source?

iPodLinux is a Linux distribution for iPods based on PortalPlayer chips: the old hard disk based iPods up to the 5th generation, and the 1st generation Nano. It's actually a port of uClinux, because the processor lacks the memory management hardware needed for ordinary Linux. iPodLinux consists of a kernel port, the Podzilla application which provides an iPod-like interface, and various modules for Podzilla which are in effect small programs.

I have iPodLinux installed on my 5th generation iPod. It's interesting but not very useful for me. I normally run Rockbox, and I've only used iPodLinux for running Smartmontools smartctl to check hard disk health. Nevertheless, I'm interested in learning more about the Linux kernel, so I just spent some time tracking down the kernel source code.

Source locations

The old home page at www.ipodlinux.org has been down for a long time. Don't bother trying Archive.org, because the site wasn't archived due to its robots.txt.

There is an ipodlinux SourceForge project. Its files section contains patches and binaries. The latest 2.4.24-ipod2 version there is old and does not contain PP502x code needed for 5th generation iPods. If you want to use it, get linux-2.4.24, apply uClinux-2.4.24-uc0.diff and then apply the ipod2 patch. You can build with the arm-elf-tools-20030314.sh toolchain.

The same SourceForge project also has a SVN repository which has a later version. The kernel was initially at trunk/linux/ and then in r2251 "The Great Befuddlement" moved it to linux/2.4/. The repository only contains changed files, so you have to take an unmodified Linux directory, apply the uClinux patch, and then copy files from the repository into that tree. This kernel builds with arm-elf-tools-20030314.sh and works with my iPod. The repository seems abandoned, with the last commit in 2009. For convenience I'm providing a Git repository of just the kernel.

The SVN repository also has a 2.6 port at linux/2.6/ but it's at a very early stage. It might partially work with some older iPod, but it certainly won't have full functionality. I didn't even get it to compile successfully yet.

The uClinux-2.4.x patches starting with uClinux-2.4.24-uc1.diff.gz also contain iPodLinux code. It seems to be a stripped-down version of the ipod0 code, meaning it's very old. This complicates attempts to upgrade later iPodLinux to a later kernel version version, but it wasn't too hard to do with a git merge.

The latest version?

Finally I found ipodlinux on GitHub. The linux-2.4.32-ipod kernel seems to contain everything from the SourceForge SVN repository, but it switches over to uClinux 2.4.32 earlier, so it is not an exact copy. After that it contains some iPod specific patches, and then various Linux fixes.

The repository contains the entire kernel, so you can simply build from there. It is meant to be compiled with a later version of the toolchain. I used arm-uclinux-elf-tools.tar.bz2 with GCC 3.4.3. It compiles without problems and works on my 5th generation iPod.

Installing the kernel

You need to convert the kernel to a binary linux.bin image. Take a look at the instructions on SourceForge. Since I mainly use Rockbox, I have the Rockbox bootloader installed. It loads /linux.bin from the FAT32 partition if I hold down the play/pause key at the bottom of the wheel. You need a separate Linux partition for iPodLinux. If you need to resize partitions, be careful, because the original firmware partition is marked as unused but is actually required.

Binaries

There are some binaries at http://rvvs89.ucc.asn.au/ipl/. This includes a Linux-2.4.32-ipod2-cc.bin.gz kernel which I was using previously. I cannot find the source for that kernel. I just installed the new kernel I compiled from GitHub source.

SansaLinux

The V1 Sansa players also use PortalPlayer chips. SansaLinux seems to be an adaptation of iPodLinux to those players. In some parts kernel code is the same but "ipod" has been replaced by "sansa". I have not investigated this in depth. It could potentually have some useful new PP502x functionality.


Friday, April 03, 2015

The Dell Inspiron 6400/E1505 hinge switch is easy to remove

My laptop would sometimes wake up from sleep while closed. After some searching online I learned about the hinge switch. Replacement switches are inexpensive, but the replacement procedure seemed complicated and involved removing the top half of the laptop.

After opening up the laptop, I found that the switch can be removed without removing the top half. Just the hinge cover and keyboard are in the way. After unplugging the switch cable beneath the keyboard, the switch can be carefully manoeuvred out.

The hinge cover was the worst part. It's easy to open the screen 180 degrees and pry it up via the slot on the right, but the clips at the left side didn't disengage easily. I was afraid I would break something, but after looking at some videos I just continued, with carefully distributed force and some wiggling. The keyboard is easy to move out of the way, with just two screws at the top and easy pry points near Backspace and Esc. There is no need to unplug it, but be careful to not put stress on the flexible cable.

I also tightened screws connecting hinges to the bottom part of the laptop. They were a bit loose and this improved things, but the plastic itself flexes anyways. The top half would need to be opened up to tighten the hinge screws there, and that involves a lot of plastic clips.

I simply took the switch out and didn't replace it. I don't think I'll miss it. It's such a tiny delicate thing! Whoever designed that part of the laptop is an idiot. I assumed they would be using a magnet and reed switch or hall effect sensor.

This picture is with the switch removed. Its location is behind the black sleeved WiFi antenna cables where they enter the top half. The oval shape of the plastic where the wires enter actuates the switch.

Monday, March 02, 2015

HTTP/2 is being used as a tool to promote encryption, and I approve of that

When I read that Firefox and Chrome will only allow encrypted HTTP/2 connections, I was shocked and disappointed. The standard itself does not require encryption, so this is an intentional limitation that those browsers chose to add.

Encryption by itself can only be trusted if you can be sure who you're talking to. Otherwise, you could have an encrypted connection to an adversary, who then makes an encrypted connection to the web server you wanted to reach. Because of this, web servers need certificates from recognized certification authorities. Without a trusted certificate, web browsers show scary warnings, as if something is horribly insecure. Firefox also makes getting around that warning annoying. In reality, such an encrypted connection is no worse than an unencrypted connection. It could be better, but you have no proof of that.

Because of these warnings, if you want to set up an HTTP/2 server, you effectively require a certificate from a recognized certification authority. This is an unprecedented limitation! The need to register somewhere to run a web server is reminiscent of what a totalitarian state might do. You generally even have to pay money, as if HTTP/2 is shareware with nag screens if you don't register.

Then I learned that StartSSL is offering free dynamic DNS and certificates. This means you can get a subdomain and associated recognized certificate for free. This gives you a way to use HTTP/2 for free, and you can probably also avoid supplying accurate personal information. It definitely helps, but having just one company in the whole world offering this isn't good.

What finally changed my opinion was thinking about the big picture. We know that there is extensive eavesdropping going on, by entities which have absolutely no respect for privacy. You can choose to use encryption wherever possible by installing HTTPS Everywhere, but many sites still don't support encryption or don't have it properly configured. HTTP/2 is being used as a tool to induce sites to start supporting encryption. What is being done with HTTP/2 may seem wrong, but it is being used to fight against something that is far more wrong. So, I think requiring encryption with HTTP/2 is justified.

Perhaps the best thing here is how those implementing new technology are leveraging that power, and not giving it away.

Friday, February 06, 2015

SDL 2 text input and Emscripten

SDL 1 used SDL_EnableUNICODE() to enable and disable text input. It started off disabled, and you needed to call SDL_EnableUNICODE() if you depended on the unicode member of SDL_keysym.

SDL 2 has a different text input API which is designed to accommodate international users and touchscreen devices. There, SDL video initialization turns on text input if an on-screen keyboard is not needed. This is normally harmless, but it causes a problem in the Emscripten port. 

Normally, many keys trigger browser actions. Those actions should be prevented if you want to use the same keys in an SDL application. In Firefox, it is possible to prevent browser actions from keypress events, but in Chrome, Safari and IE they need to be prevented in keydown events. However, preventing default actions from keydown events prevents keypress events which are needed to get text characters.

If you need to prevent browser actions and don't need SDL 2 text input, simply disable text input after initializing SDL video:
if (SDL_IsTextInputActive()) SDL_StopTextInput();

You can find more information about these JavaScript events on quirks.org. They also have a test page which you can use to examine their behaviour on different browsers.