DMP1 Reverse Engineering Notes

From Omnifi Wiki

Jump to: navigation, search
Quick Links
Linux-Inside.jpg
Related topics
  • Find Something
    • To Put Here

edit

Reproduced with permission from the author: Andy Poling

v1.0 - initial release

Contents

Introduction

  • For information on the hardware, the firmware and boot sequence, see DMS1 Hacking

This document details what I have reverse engineered about the interface between applications and the kernel device drivers that SimpleDevices added to the linux kernel.

There are two devices in /dev that act as the primary interfaces to the system: sermodr and sermodq. Virtually all communications is in small "packets" of character data with the first three characters indicating the data packet type.

/dev/sermodr is a read-mostly (I haven't seen SC write to it yet) device that provides status and button press events from the remote control panel, as well as responses to queries (such as battery voltage or temperature and fan state). It does _not_ heed the O_NDELAY flag, but instead will block reads until it has something to say.

/dev/sermodq is a write-mostly (I haven't seen SC read from it yet) device to which we send queries to access the various features of the device: the LCD, power management, etc. It does _not_ correctly respond to write() syscalls with a return value representing how many bytes were written, instead returning arbitrary values like "9" that may mean something, but who knows.

There are three devices that accomodate music play: /dev/dsp, /dev/wavdsp and /dev/wmadsp.

/dev/dsp will accept MP3 data, decode it, and send it to the DSP. It will accept large blocks of data that do not necessarily fall on MP3 frame borders.


/dev/sermodr

Reports on /dev/sermodr have three leading bytes that identify the type of report and the size of the data. The first two bytes identify the report type, while the third byte is the size of the remainder of the report.

Here are the various reports from the sermodr device that I've reverse-engineered to date:

115: Control Pad button and dial events

control pad events are reported as an 8-byte character stream that looks like

115-n001

The "115", in conbination with a size of 8 allows us to recognize this as a control pad report.

The fourth character ("-" in my example above) will contain either "-" or a control pad button press event. A "-" indicates no button pressed. The buttons are reported by the following characters:

    Faceplate Return Codes
    Function Reported Char
    HOME
    H
    ARTIST
    Z
    ALBUM
    A
    GENRE
    G
    FAV
    J
    REPEAT
    E
    SHUFFLE
    F
    TAG
    T
       
    PRESET
    B
       
    PLAY/PAUSE
    C
    STOP
    K
    LEFT ARROW
    L
    RIGHT ARROW
    R
    NEXT
    N
    PREVIOUS
    P
    SELECT
    S
       
    POWER
    O

The fifth character ("n" in my example") reports rotary encoder (jog dial) activity. "n" indicates no motion, while "r" indicates a clockwise rotation of one click and "l" indicates counter-clockwise rotation of one click.

The sixth character ("0" in my example) is unknown. I have never seen a report of anything but zero. It is possible it's the "tens" digit of the following, enabling reports of 10-99.

The seventh character ("0" in my example) reports repeated keys. It will report a numeric digit for the repeat count, e.g. "2" for a double press. The control pad does implement key repeat if you hold down a button. In fact, it's pretty aggressive, and thus my reader code includes de-bouncing for the various button press events.

The eighth character ("1" in my example) indicates control pad active. It will report "1" if the control pad is "on", and "0" if the control pad is off (LCD dark, and not displaying anything).

0A8: Clock

The sermodr device periodically (every 2 seconds) reports what appears to be a running clock:

0A8001A6974

The 11-byte size and the "0A8" distinguish this report. I have been unable to correlate this clock to the realtime clock in terms of it's value, but it does increase 2 every 2 seconds.

**See DMP1 System Time Hacking for a full write up on how the clock and onboard timer works ~lumkichi

1D2: Power alerts

When the system has a power down pending, sermodr will provide a 5-character countdown timer, reported every 2 seconds:

1D23A

The "1D2" indicates a poweroff pending event. The time-left value is the 4th and 5th characters ("3A" in my example) and is in hex. The 0x3A in this example indicates 60 seconds to power-off. This will occur when the ignition key is turned off or disk eject button has been pressed. You can stave off power-off (e.g. in order to perform a "sync" of the music collection) using a "2bD" command (see below).


0C7: Battery Voltage

The sermodr device reports system status as well. It can report battery voltage:

0C72E50001

"0C7" is a battery voltage report, and the 3rd thru 5th characters ("2E5" in my example) in hex indicate the voltage. I turned on the headlights and heater fan on my car for a few minutes, then turned them off and hooked up a battery charger. I watched the reported value sink to 0x26f under load and rise to 0x337 on the charger and then stabilize and flutter around 0x32A-0x32E as the charger went into trickle charge mode. According to "pmee" this is the "A/D counts" for voltage. When this drops below "Vacc shutdown time" (0x203 or 515 on my DMP1) the hardware triggers a shutdown counting down from "Low voltage shutdown time" (0xE or 14 on my DMP1). These two values are settable with pmee.

0B7: Internal Temperature

Another status it can report is the internal temerature. It looks like:

0B71002861

"0B7" is a temperature report. I don't know if it's from the disk temperature sensor or a sensor on the motherboard itself. I'm betting on the disk sensor because the temperature seems to track somewhat with disk activity level. The 7th thru 9th characters ("286" in my example) represent the temperature. According to "pmee" this is the "A/D counts" for temperature.

When this exceeds the PM value for "Fan temp high" (0x2A3 or 675 on my DMP1), the fan turns on. When this is below "Fan temp low" (0x28A or 650 on my DMP1) the fan turns off. These two values are settible with pmee.


1K6: PM EEPROM reports

The sermodr device will report the contents of the power mgmt "eeprom" in response to queries and set requests.

1K601028A

The 4th and 5th characters ("01" in my example) are the "index", while the 6th thru 9th characters ("028A" in my example) are the reported value.


/dev/sermodq

Again, everything we write to /dev/sermodq has a 3-character prefix that identifies the request type, and determines the size of the packet we write.

The requests seem to be of two main types:

"2" requests: requests to the system controller
"3" requests: requests to the LCD/control pad


2bD: Power off

example: 2bD00

When you make this request, the cpu and disk will power off. The control pad will be unaffected. Under most circumstances where this is appropriate (ignition off, disk eject) the control pad is either already off due to loss of ignition power, or would typically indicate the disk is ejecting.

I'm guessing that SC intuits the difference between these events by the presence of the control pad active indicator. If you get power-off events and the control pad is active, then the disk eject button has been pressed. If you get power-off events and the control pod is inactive, then the ignition has been turned off.

2nC: Request voltage report

example: 2nC

Requests the voltage report documented above.

2nF: Heartbeat / watchdog pet

example: 2nF

The hardware has a watchdog timer built in. If it expires, it causes a reboot of the system. When the watchdog is enabled (see below), you need to periodically pet it using this command.

sermodq will respond with a "1FA" report, such as "1FA0000100021".


2nB: Battery voltage report request

example: 2nB

This requests the battery voltage report documented above.


2nA: Time report request

example: 2nA

This request will produce a "08A" hardware clock report (such as "0A800312828") on sermodq.


2dE: Wakeup timer set

example: 2dE00312B78

This will set the wakeup timer value to the value (evaluated against the time report value shown above) expressed by characters 4-11. It will also return a "1E8" report (such as "1E800312B78") of the wakeup timer value.

**See DMP1 System Time Hacking for a full write up on how to set onboard timer ~lumkichi

2bD: Shutdown timer set

example: 2bD3C

This wil set (reset) the shutdown countdown timer to the value expressed in hex in characters 4 & 5. It will produce a "1D2" response on sermodq indicating the current value of the timer (which should match what was requested).


2nG: Unknown status report

example: 2nG

This produces a status report of some kind - meaning as yet unknown. It produces on sermodq a "0G2" report (such as "0G20b").

3n2: Unknown report request

example: 3n2

This request will produce a "12A" report on sermodq (such as "12A0000010061"). It's purpose is unknown.

3h3: LCD draw requests

There are several sub-request types:

3h3GB - clear LCD display

3h3PS - display the "STOP" (square) symbol in the lower right corner

3h3PP - dispaly the "PLAY" (triangle) symbol in the lower right corner


3i3: set progressbar in play mode

example: 3i364

Sets the percent (0x0-0x64, 0-100) of the play progress bar when in play mode.


3k3: display a line of text

example: 3k311NHello World

This displays text on one line of the LCD. The 4th and 5th characters specify (twice - go figure) the row to display on (0-2). The 6th character indicates whether to display arrows (N=none, L=left, R=right, B=both) on the sides.

I use this for the play mode screen in my player application.

3m3: display time in play mode

example: 3m3 0:00:00<some binary data>

Since I don't use the play mode (it basically wastes most of the 3rd line of the LCD), I didn't bother to reverse engineer this beyond determining it's basic functionality.


303: display a vertical list

example: 3032N6405Hello05There05World

This displays a vertical list with a scrollbar and is suitable for menu use. The 4th character ("2" in my example) indicates the "active" row, which is displayed in reversed colors (black on white); "." indicates no row is active. The 5th character ("N" in my example) indicates whether to put arrows on the "active" row (N, L, R, B). The 6th and 7th characters indicate the scrollbar percent (0x00-0x64, 0-100). Then the first row is specified as a 2-character hex character count followed by the text. Same for the second and third rows. If a row is to be empty, a size of "00" and nothing further will suffice.

The menu system in my application uses this to display menu screens.

3p3: Play modes

There are a group of sub-requests:

3p3PoSome Text - set the top line text to "Some Text" and enter play mode

3p3Eoo - set the "Pause" (two vertical bars) indicator in the bottom right corner

3p3PR - set the "repeat" indicator in the bottom right corner

3p3PS - set the "shuffle" indicator in the bottom right corner


See Also

  • DMP1 Reverse Engineering Notes Findings by Andy Poling on how the faceplate talks to the DMP1
  • DMP1 System Time Hacking Findings on how to work the onboard Real Time Clock and Wake Up Alarm (for those wireless syncs!)
  • Logging Into The DMP1 Get on there and play!
  • DMP1 Replacement Kernels Dan Zenchelsky's findings on loading a replacement kernel into the DMP1
  • DMP1 Enabling a Serial Port Ingenious findings by Dan Zenchelsky on how to gain access to DMP1 kernel through a hidden serial port

External Links


Lumkichi 09:12, 9 Nov 2005 (CST)

Personal tools