Tuesday, November 05, 2013

Enable volume keys in Flash Player using a hotkey program

Flash Player running in Firefox in Windows 7 steals keyboard events when focused. This is a well known bug that has been around for a while and isn't getting fixed. There are many Firefox and Flash bug reports on the issue. It should probably be considered a Flash bug, not a Firefox bug.

This affects all Firefox keyboard shortcuts, such as Control+Tab for switching to the next tab. It also affects some keys that Windows normally handles, such as volume up, volume down, and mute. Fortunately, it doesn't affect keys handled by HoeKey, a hotkey program. This means the problem with volume keys can be fixed by handling volume keys via HoeKey, instead of directly through Windows. Here is what needs to be added to the HoeKey configuration file:

173=Msg|Progman|793|0|524288 ; mute
174=Msg|Progman|793|0|589824 ; vol down
175=Msg|Progman|793|0|655360 ; vol up


I expect other hotkey programs could do the same thing. I like HoeKey because it uses minimal system resources, it works perfectly, and is free.

Monday, April 01, 2013

Running code on the Mercury ME-DPF24MG digital photo frame

In my previous post, I reported reverse engineering findings about the Mercury ME-DPF24MG digital photo frame. Once I figured out the most important things, it was time to start running custom code on the frame.

If firmware page 0 was writable, I would have just flashed a modified version of the code used for other Sitronix frames. Instead, I extended the "get version" command to enable displaying the USB DMA buffer for data sent by the host, and running code there. The command is parsed at flash offset $A40B, which is at $640B in firmware page 2. At that point code has access to the first 16 bytes of the sector at $381, and the last 64 bytes of the sector in the DMA buffer at $200. I used the first 4 parameter bytes at $382-$385 to trigger my code. Here is an example of the display function:


I displayed the text by calling the same function used by the message command. This is not practically useful for displaying messages, but it can confirm that my code works, and that data in the USB DMA buffer can be used.

(After the first 64 bytes, you see the DMA buffer for data being sent to the host, which starts with USBS because it is a USB mass storage status reply. The green and pink corruption outside is because the firmware upgrade code overwrites the second picture and pictures are stored in a compressed format. To prevent overwriting the code doing the firmware upgrade, the new firmware is first written there, and then copied to its final position using code copied to RAM.)

Then it was time to run code. It worked, but 64 bytes isn't much space. It wasn't even enough for the LCD set window code. At $580-$67F there is 512 bytes of RAM where flash writing procedures are copied. Since code is always copied there immediately before being executed, that area is free when not writing to flash. I wrote a small program which copied part of the USB DMA buffer to that free area. Then I used this code appended with small chunks of a longer program to assemble a longer program at $580.

Finally, this allowed me to display images. I wrote code which interacts with the USB interrupt handler to read packets sent to the data port. This is very simple. I just had to deal with a few flags and call one function after I received a packet. For faster performance, it should be possible to use polling for everything except the start and end of a packet.

Probing the device using code


The ability to run code and dump RAM also allowed me to probe the device and discover information about its hardware. By looking at flash ID bytes and the Common Flash Interface (CFI), I found that the chip is an Eon EN29LV320B in bottom boot configuration. It reports that the first two sectors are protected, but I don't know if that's due to a protection setting stored in flash or a result the WP#/ACC pin, which protects the first two sectors when low. I suspect it's due to the pin. Maybe it's connected to a GPIO pin? I also probed the LCD controller and found that it is the Ilitek IL9320.

Port A is connected to the buttons, with bits being normally high and going low when the button is pressed:
PA & 1 = left
PA & 2 = pause
PA & 4 = right
PA & 8 = menu
The slide switch seems to simply cut power, so there is no way to read it. The pause button is read at startup, changing program flow. It might be for entering a recovery mode, not calling photo frame code and immediately going into USB mode.

This is still a work in progress and I'm not releasing any code now. If you want some code, feel free to ask.

Friday, March 29, 2013

Mercury ME-DPF24MG digital photo frame reverse engineering

I got two Mercury ME-DPF24MG digital photo frames at the Leamington Zellers liquidation sale at 70% and 80% off the yellow tag price. They're nice 2.4" photo frames with a 320x240 LCD, rechargeable battery, a magnetic back, and a leg for standing the frame up on a desk. Some reverse engineering has already been done by others, but it's incomplete and the frame cannot be used as USB controlled display yet. The frame is also similar to the Technaxx Magno, which has been investigated more thoroughly but still cannot be used as a display.

Basic information


The frame has 4 megabytes of flash memory. The manual claims "32 MB", but I guess they mean 32 megabits. Phack from st2205tool-1.4.3 does a check for the amount of memory, and quits with "Expected response 8 on cmd 1, got 0x1f!" because the frame reports more memory than expected. Here is the external memory map, in terms of 32 kilobyte (0x8000 size) pages:

0x000-0x07F flash, starting with firmware in pages 0 and 1.
0x080-0x2FF unused
0x300-0x37F LCD
0x380-0x3FF 4 pages repeating, similar to firmware
0x400- address space repeats, probably because bank register ignores bits

The area at 0x380 seems to contain a firmware for a different photo frame. The menus are smaller than in the true firmware, implying it is for a lower resolution. Maybe it is ROM inside the chip? I did not investigate that area further.

The read command adds two to the low byte of the page number. As a result, a normal read starts right after the firmware. I dumped the firmware by reading in page 0xFE, because when firmware adds 2 to that number, it gets 0. I used 0xFE, not 0xFFFFFFFE because the firmware only adds 2 to the least significant byte of the page number.

The chip is probably a Sitronix ST2203U. It is definitely not a ST2205U because the DMA controller is different. I wasn't able to find a full User's Manual for that chip, but the ST2205U and ST2202U manuals are helpful. RAM is at 0x80-0x880 internal addresses, meaning there is only 2 kilobytes.

The LCD controller is unknown, and probably similar to Ilitek ILI9325C. The command number is 16 bit, with the most significant byte first, and coordinates are input the same way.  To talk to the LCD, set DRR to $300, send commands to $8000 and send data to $C000. Here is a sequence for setting a rectangle: C=$20, D=Y1, C=$51, D=Y1, C=$51, D=Y2, C=$21, D=X1, C=$52 D=X1, C=$53, D=X2, C=$22, followed by data with 3 bytes per pixel. This is untested.

Sunday, March 24, 2013

ROM dumping via the sound card

Once I got code running on the RCA RC3000A, the first task was dumping the TCC760 boot ROM and the SST39VF1601 firmware flash. The resistor I soldered for entering USB boot mode provided a convenient connection point for GPIO_B[22]. The chip runs at 2.5V, and that voltage should not be too high for line in. I carefully used an alligator clip to connect it to the tip of a 1/8" plug:

I transferred data serially using a simple ARM assembler program. Zeroes are a short pulse and ones are longer pulses. There is a short pause between bits, and a longer pause between bytes. Here is an example of 11000101 binary. I sent the least significant bit first because right shifts conveniently move it into the carry flag.
Dumping the two megabyte flash chip took an hour and a half. That's not a problem, so it's not worth investing effort in a faster communication method. For larger amounts of data, the TCC76X USB device controller would be a better choice. It seems very easy to use.

The 4KB TCC76X boot ROM has MD5 value 2579641d5be434eea15f4ec3c27a5f53. It implements USB boot mode and secure modes. However, it is not part of the normal operation of the RCA RC3000A. The boot mode is set 000, and execution starts from the SST39VF1601 firmware flash.

The 2MB firmware flash has MD5 value 89ae93fedd7fc5dff0f118aebdd4c7b6. Text strings identify it as "Thomson D100", "V2.20" and "2006.07.13". Apparently unused space with 0xFF bytes starts at 0x92E00, though there is a small chunk used at 0xFE000-0xFE0B2. This means there should be plenty of space for adding a second firmware for dual boot.

Friday, March 22, 2013

Telechips TCC76x USB boot

In my previous post I opened up my RCA RC3000A and enabled USB boot on the Telechips TCC760 SoC. I'm now able to run code on it. The USB boot mode is a bit different than on later Telechips devices which are supported by the Rockbox tcctool utility. The last parameter is not the SDCFG register value, but the start address. Here is a bit of information about the USB boot mode.

All communication is in 64 byte packets. The first packet contains parameters for the USB loader routine. It must be 64 bytes, but all that matters is the first four 32-bit words:
  1. Must be 0xF0000000. If it does not match, the loader will try to use the next packet as the parameter packet, and so on, repeating. 
  2. The number of data packets, or in other words, total data size divided by 64. The loader will receive this number of 64 byte data packets after the parameter packet, and store them sequentially in memory.
  3. The destination address. The loader will store the first data packet starting at this address and store other data packets after it. The loader has no capability for performing the special actions needed to write to flash, so this must be RAM.
  4. The start address. Once the loader has received the specified number of data packets, it will jump to this address.
Note that since SDCFG is not configured, the SDRAM cannot be used and the upload should be to SRAM. The SRAM is 64 kilobytes from 0x30000000 to 0x3000FFFF, and it's also mapped to appear at 0x00000000 to 0x0000FFFF. The boot ROM is 4 kilobytes and copied to the start of SRAM, and it must not be overwritten while it is running there. You can start code at 0x00001000 or 0x30001000. The following tcctool entry can be used:

{"rc3000a",  "RCA RC3000A",                     0xb001, 0x00001000, 0x00001000 },

Thursday, March 21, 2013

RCA RC3000A disassembly and USB boot enabling

The RCA RC3000A is a small boombox with MP3 playback and recording. There is 512M flash, support for SD cards and USB storage devices, an FM radio and line in. Opening it up is kind of difficult due to plastic clips at the inner ring, around the hole. I finally got it open by applying force at the thinnest part at the front. Note how the front and speakers are attached to the top with screws, so only the bottom black part is removed.

Here's a closeup of the main board. There isn't much to see, because it is obscured by copper shielding foil and a speaker assembly.

More can be seen after removing the foil and speaker assembly. However, it's not very interesting. That's just the data flash and 2 MB of SDRAM. The SoC running it all must be hiding on the other side.

Detaching the circuit board is easy. However, the SoC is still hidden behind the LCD support.


After carefully removing the LCD support, I can see that the SoC is the Telechips TCC760. The datasheet is available!

Here's the TEA5767 FM radio:

This is the CS42L51 CODEC. To the left, R59 through R60 are 47 kΩ pulldown resistors which set the TCC760 BM (boot mode) bits to 000, meaning NOR boot without encryption. Making the right side of R60 high at reset time will change BM to 010 and select USB boot instead.

This can also be done on the other side. The capacitor pin closest to the speaker connector is +2.5V and the bottom short trace near the corner of the foil is BM1. I'm using a resistor rather than a short because the same pin is used for LRCLK for the CODEC. Yeah, it's messy, but it's temporary. I'd like to install a switch after I figure out how to run code.

Here's what shows up in Device Manager:

It might be possible to use the Rockbox tcctool program to upload code. A single one line change adding the device to the device list enables uploading, but I have not been able to confirm that any uploaded code actually runs.

The USB device ID is supported by the TeleChips firmware download driver vtcdrv.sys found in iAUDIO_COWON_D3_Upgrade_V4.53GL. There is also a VtcUsbPort.dll in the upgrader. Using these would require reverse-engineering the API. I'm hoping a simple change to tcctool will make this work.