DMP1 Reverse Engineering Notes
From Omnifi Wiki
| Quick Links |
![]() |
| Related topics |
|
Reproduced with permission from the author: Andy Poling
v1.0 - initial release
Introduction
- For information on the hardware, the firmware and boot sequence, see DMS1 Hacking
- For information on this project (OpenFi, a play on Omnifi), see *Openfi Sourceforge Project
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:
| Function | Reported Char |
| HOME | |
| ARTIST | |
| ALBUM | |
| GENRE | |
| FAV | |
| REPEAT | |
| SHUFFLE | |
| TAG | |
| PRESET | |
| PLAY/PAUSE | |
| STOP | |
| LEFT ARROW | |
| RIGHT ARROW | |
| NEXT | |
| PREVIOUS | |
| SELECT | |
| POWER |
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)
