MPU communication

Started by a1ex, July 22, 2016, 11:26:59 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

leegong

Payload of msg 09 14  includes  short integer LensFocusPosition and long integer timing 

leegong

 Lens max aperture , minimum aperture , Lens ID , Wide FocalLength , tele Focal Length ...... are inside msg 03  15

leegong

Any description or info of any Msg is appreciated ,  for example msg 05 02 , msg 09 17 , msg 08 02......

BBA

I am interested in your work and would have some questions about your findings (if possible).

JP79dsfr has shared his work on the EF communication protocol between lens and body : cfr http://www.magiclantern.fm/forum/index.php?topic=18308.msg184575#msg184575 .

It is an amazing work that only a passionated specialist could do : Merci beaucoup, JP, pour ce travail incroyable / Many thanks, JP, for this amazing work.

I think the message you are referring to are the same ones as those referenced in his work.

French is my mother language : I have difficulties in english (sometimes 'google traduction' is necessary).

If you have difficulties in french, I can try my best to translate in english some parts of his work as it is quite impressive (pdf : 95 pages).

I think it is best to translate next to the original text and to keep both in parallel.

g3gg0

it would be cool if you could merge your findings. e.g. in the magic lantern wiki on wikia? http://magiclantern.wikia.com/wiki/
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

leegong

Quote from: g3gg0 on August 04, 2017, 04:46:48 PM
it would be cool if you could merge your findings. e.g. in the magic lantern wiki on wikia? http://magiclantern.wikia.com/wiki/
So sorry , my english is too bad to writting in  the magic lantern wiki , so many types of msgs as you know .   
however i'll be glad to share my findings here or sending to anyone if he writes info of MPU msgs  in  the magic lantern wiki .

leegong

MPU reports Lens status in Msg09 05 to CPU , 4 bytes in Msg09 05 payload,
the last one is probablly ERCD of Lens communication :
0x00 : good
0x02 : no 0xAA response from Lens after sending Lens CMD 0xA
0x20 : Lens-Camera RTX timeout 
Any info of Msg09 05 on CPU side ?

a1ex

I have a couple of messages described on the QEMU branch: extract_init_spells.py. This script parses a startup-log and outputs a header file with the MPU conversation, with comments where the spells are known. Example: 60D.h, 50D.h.

My startup logs used to create the above headers are here (unzip under qemu/startup-logs).

Summary for the hardcoded spells:

- 06 05 06 ARG1 ARG2 00 (MPU -> main CPU): MPU button codes. In bindReceiveSwitch, they are translated into GuiMainTask codes, aka BGMT codes from platform/*/gui.h - see extract_button_codes.py and button_codes.h).

- 06 05 04 00 ARG1 00 (Main CPU -> MPU): NotifyGUIEvent, called by SetGUIRequestMode (used for switching GUI modes, e.g. for going to Canon menu or to PLAY mode). ARG1 is the requested GUI mode. The message is acknowledged by 06 05 04 00 ARG1 01 PROP_GUI_STATE (see NotifyGUIEvent.h); 500D uses ARG1 AA but seems to accept ARG1 01 as well.

From the QEMU thread:
- Detailed description of MPU button codes and GUI modes
- Parameterized MPU spells

Example - entering Canon menu (5D3 1.2.3; 5D3-halfshutter.log):

76243> **INT-36h*:000afa38:00:00: *** mpu_recv(06 05 06 00 01 00), from ff2e87f8
7632D>   MainCtrl:ff0cc258:89:03: bindReceiveSwitch (0, 1)
7634B>   MainCtrl:ff0ded40:85:03: GUI_Control:6 0x0                 # 5D3 gui.h: #define BGMT_MENU 6
7676F>    CtrlSrv:ff35d70c:83:03: IDLEHandler PRESS_MENU_BUTTON
767A8>    CtrlSrv:ff18b6e4:83:03: SetGUIRequestMode(2)
767CE>    CtrlSrv:ff0dedc0:83:03: NotifyGUIEvent(1)
78983>    PropMgr:000af9d8:00:00: *** mpu_send(06 05 04 00 01 00), from ff12298c

8004D> **INT-36h*:000afa38:00:00: *** mpu_recv(06 05 04 00 01 01), from ff2e87f8
80208>   MainCtrl:ff146e3c:9c:16: PROP_GUI_STATE 1
80508>    PropMgr:ff0cca34:89:03: GUI_STATE : PLAYMENU


The GUI mode switch can be initiated by the MPU as well. Example: pressing half-shutter while in Canon menu will close the menu first, and afterwards will send the half-shutter event (5D3-halfshutter.log):

0DB27> **INT-36h*:000afa38:00:00: *** mpu_recv(06 05 04 00 00 01), from ff2e87f8
0DD57>   MainCtrl:ff146e3c:9c:16: PROP_GUI_STATE 0

13B86> **INT-36h*:000afa38:00:00: *** mpu_recv(06 04 05 00 00), from ff2e87f8
13C2D>   EventMgr:ff208480:8d:03: emDeliverMulticastEvent : SW1ON
13D53>   MainCtrl:ff146348:89:05: EVENTID_METERING_START

316D3> **INT-36h*:000afa38:00:00: *** mpu_recv(06 04 05 0b 00), from ff2e87f8
3173D>   EventMgr:ff2085f8:8d:03: emDeliverMulticastEvent : SW1OFF
31828>   MainCtrl:ff0cd96c:89:05: EVENTID_METERING_TIMER_START





- ?? ?? 0a 08 ... is PD_NotifyOlcInfoChanged (updates shooting info; variable length)

- 06 05 04 01 ARG1 00 (initiated from main CPU, acknowledged by MPU with the same message): PROP_ICU_UILOCK (see UILock.h). Argument is a bit mask of what button groups to lock, see property.h.




On the CPU side, 09 05 appears to trigger PROP_LV_EMD_DRIVE_RESULT; only used in LiveView. Will upload some logs here:

5D3-mirror-up.log
5D3-123-startup-lv1.log
700D-startup.log

Unique entries:

5D2:
FD4AC> **INT-36h*:000962c8:00:00: *** mpu_recv(0a 08 09 05 00 80 00 00 00), from ff99f6cc
249A2> **INT-36h*:000962c8:00:00: *** mpu_recv(0a 08 09 05 00 83 00 00 00), from ff99f6cc
58E38> **INT-36h*:000962c8:00:00: *** mpu_recv(0a 08 09 05 00 81 00 00 00), from ff99f6cc

5D3:
F18FA> **INT-36h*:000b0330:00:00: *** mpu_recv(0a 08 09 05 00 00 00 01 00), from ff2e4494
E8FEB> **INT-36h*:000af114:00:00: *** mpu_recv(0a 08 09 05 00 00 00 00 00), from ff2e87f8

EOSM:
**INT-36h*:000dfccc:00:00: *** mpu_recv(0a 08 09 05 01 00 00 00 00), from 1dedc

700D:
**INTERRUP:000c5e3c:00:00: *** mpu_recv(0a 08 09 05 00 00 00 01 00), from ff31af1c

500D:
8680B> **INT-36h*:00092a1c:00:00: *** mpu_recv(0a 08 09 05 00 00 00 01 00), from ff18aa38
EE0F0> **INT-36h*:00092a1c:00:00: *** mpu_recv(0a 08 09 05 00 10 00 00 00), from ff18aa38
AA753> **INT-36h*:00092a1c:00:00: *** mpu_recv(0a 08 09 05 20 00 00 00 00), from ff18aa38

dfort

The links to the log files are broken.

a1ex

Solved.

Next, I'd like to show some (recent) techniques for checking what these MPU messages are for. Of course, the first step would be to look at mpu_send and mpu_recv (stubs available on the dm-spy-experiments branch on some models, but I'm thinking to make them available everywhere). However, these functions are pretty generic.

The first thing you can do is to look up the MPU message in the logs, and then examine the nearby messages. Things are made difficult by the multitasking environment; furthermore, MPU functionality is often delegated to or from other tasks.

For mpu_send (from main CPU to MPU), you could check the caller (reported in the dm-spy logs as LR), or the full stack trace. There are a couple of approaches:
- compile ML with debug information (-ggdb3), then run it under QEMU+GDB (example).
- in QEMU you also have the option to use -d callstack or -d calls.
- on the camera, you can also get a limited stack trace (call backtrace_getstr from the mpu_send hook in the dm-spy-experiments branch).

Many mpu_recv calls are followed by msg_queue_send. Tracing these calls and matching them with the corresponding msg_queue_recv from other tasks is helpful.

Todo: some examples.

leegong

@a1ex , some decodings in 550D MPU FW :
Msg 06 01 = Display
Msg 06 03 = Play
Msg 06 04 = EraseButton
Msg 06 0A = AE_Lock
Msg 06 0C = Set button
Msg 06 11 = LockSW
Msg 06 12 = CardCover
Msg 06 13 = BatCover
Msg 06 18 = CrossUp
Msg 06 19 = CrossDown
Msg 06 1A = CrossRight
Msg 06 1B = CrossLeft
Msg 06 1C = AVbutton
Msg 06 1E is strongly related to mestimer starting
Msg 06 21 = RECstart

a1ex

They seem to match (QEMU button_codes.h):


static int button_codes_550D[] = {
    [BGMT_INFO]                         = 0x0101,
    [BGMT_LV]                           = 0x2101,
    [BGMT_MENU]                         = 0x0001,
    [BGMT_PLAY]                         = 0x0301,
    [BGMT_PRESS_DOWN]                   = 0x1901,
    [BGMT_PRESS_LEFT]                   = 0x1B01,
    [BGMT_PRESS_RIGHT]                  = 0x1A01,
    [BGMT_PRESS_SET]                    = 0x0C01,
    [BGMT_PRESS_UP]                     = 0x1801,
    [BGMT_PRESS_ZOOM_IN]                = 0x0901,
    [BGMT_PRESS_ZOOM_OUT]               = 0x0A01,
    [BGMT_Q]                            = 0x0201,
    [BGMT_Q_ALT]                        = 0x0501,
    [BGMT_TRASH]                        = 0x0401,
    [BGMT_UNPRESS_DOWN]                 = 0x1900,
    [BGMT_UNPRESS_LEFT]                 = 0x1B00,
    [BGMT_UNPRESS_RIGHT]                = 0x1A00,
    [BGMT_UNPRESS_SET]                  = 0x0C00,
    [BGMT_UNPRESS_UP]                   = 0x1800,
    [BGMT_UNPRESS_ZOOM_IN]              = 0x0900,
    [BGMT_UNPRESS_ZOOM_OUT]             = 0x0A00,
    [BGMT_WHEEL_DOWN]                   = 0x0E01,
    [BGMT_WHEEL_LEFT]                   = 0x0DFF,
    [BGMT_WHEEL_RIGHT]                  = 0x0D01,
    [BGMT_WHEEL_UP]                     = 0x0EFF,
    [GMT_GUICMD_OPEN_BATT_COVER]        = 0x1301,
    [GMT_GUICMD_OPEN_SLOT_COVER]        = 0x1201,
    [GMT_GUICMD_START_AS_CHECK]         = 0x1100,
};

a1ex

Here's how the full shutter event looks like:


971C5> **INT-36h*:000afcec:00:00: *** mpu_recv(06 05 03 54 00 00), from ff2e87f8
97204> **INT-36h*:000afaf0:00:00: *** TryPostEvent(PropMgr, 0xa, 0x71c7f0, 0x14), from ff123cf8
97292> **INT-50h*:ff13b96c:00:01: [PM] DisablePowerSave (Counter = 3)
972B8> **INT-50h*:ff13b9dc:00:01: [PM] EnablePowerSave (Counter = 2)

97320> **INT-36h*:000afcec:00:00: *** mpu_recv(06 04 05 01 00), from ff2e87f8
97355> **INT-36h*:000afaf0:00:00: *** TryPostEvent(EventMgr, 0x2, 0x1, 0x712e98), from ff0f5308
973E5> **INT-50h*:ff13b96c:00:01: [PM] DisablePowerSave (Counter = 3)
9740D> **INT-50h*:ff13b9dc:00:01: [PM] EnablePowerSave (Counter = 2)

97476> **INT-36h*:000afcec:00:00: *** mpu_recv(06 04 05 0e 00), from ff2e87f8
974A8> **INT-36h*:000afaf0:00:00: *** TryPostEvent(EventMgr, 0x2, 0xe, 0x712f2c), from ff0f5308
974E9>   EventMgr:000afaf0:00:00: *** TryPostStageEvent(Fstorage, 0x9, 0x712e98, 0x0), from ff0e06b8
9752A>   EventMgr:000afaf0:00:00: *** TryPostStageEvent(ShootCapture, 0x11, 0x0, 0x0), from ff0dab30
97585>   EventMgr:000afaf0:00:00: *** TryPostEvent(Gmt, 0x15, 0x1, 0x0), from ff174510
975D9>   EventMgr:ff208818:8d:03: emDeliverMulticastEvent (ID = 14)
97615>   EventMgr:000afaf0:00:00: *** TryPostEvent(RscMgr, 0xc, 0x712f2c, 0x0), from ff0ed1b4
97656>   EventMgr:000afaf0:00:00: *** TryPostStageEvent(ShootCapture, 0x1, 0x0, 0x0), from ff0dad98
976E8> **INT-50h*:ff13b96c:00:01: [PM] DisablePowerSave (Counter = 3)
97716> **INT-50h*:ff13b9dc:00:01: [PM] EnablePowerSave (Counter = 2)
97749> ShootCaptu:ff14b98c:93:03: scsReleaseOn
9779D> ShootCaptu:ff147918:93:03: scsReleaseStart


This also shows how the MPU events are dispatched to other tasks; would be nice to draw it somehow.

leegong

@a1ex , event of SW1 and SW2 in 550D MPU FW are not sent in Msg 06  ,
i guess they are strongly related to half shutter and full shutter pressing ,
i'm going to check how they work .

@a1ex , LensIDs are described in Canon Exif Tags  https://sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html
do you know , in which kind of MPU Msg , LensID mentioned above is sent to CPU ?   



 

a1ex

Yes, SW1 and SW2 are not like regular button events. Currently I emulate SW1 (half-shutter) like this:


0x06, 0x05, 0x06, 0x26, 0x01, 0x00 (COM_SW_SOMETHING / GUICMD_PRESS_BUTTON_SOMETHING, valid on 60D and newer models, not sure what it does)
0x06, 0x04, 0x05, 0x00, 0x00, 0x00 (press)
0x06, 0x04, 0x05, 0x0B, 0x00, 0x00 (unpress)


This does trigger the SW1 property and I remember it even changed something on the exposure indicator, but it doesn't get out of Canon dialogs (e.g. if pressing half-shutter while in Canon menu).

For LensID, the 500D startup log from the archive in my previous post was taken with a 24/2.8 STM, and its info gets displayed on QEMU. Not sure which are the messages that actually contain the lens info - will brute-force them later.

a1ex

06 05 01 00 MODE 00: change shooting mode (PROP_SHOOTING_MODE).

06 05 06 1c 01 00 / 06 05 06 1c 00 00: possibly Av press/unpress
- 500D: not forwarded to GuiMainTask, but followed by bindReceiveNewTFTOLC; see BGMT_AV in 1100D gui.h
- 100D: same MPU button code, but forwarded to GuiMainTask like all other buttons.

a1ex

Quote from: leegong on August 28, 2016, 03:37:06 PM
On EOS-550D ,TX19a  may send the following msg to main CPU :
char msg[] = { 0x04, 0x05, 0x00, 0x00 };  // ae start
char msg[] = { 0x04, 0x05, 0x01, 0x00 };  // rel start
char msg[] = { 0x04, 0x05, 0x05, 0x00 };  // rel end , or bulb end
char msg[] = { 0x04, 0x05, 0x06, 0x00 };  // rel cancel
char msg[] = { 0x04, 0x05, 0x07, 0x00 };  // ae stop
char msg[] = { 0x04, 0x05, 0x0B, 0x00 };  // ae timer start
char msg[] = { 0x04, 0x05, 0x0E, 0x00 };  // related to rel
char msg[] = { 0x04, 0x05, 0x0F, 0x00 };  // related to rel


These match the messages I've been using for half-shutter emulation :)

On my logs, "release end" aka SW2OFF appears to be 06 04 05 04 00.

06 04 05 01 00 is probably "release on" (scsReleaseOn) and 06 04 05 0e 00 is probably "release start" (scsReleaseStart).

a1ex

Quote from: leegong on September 08, 2017, 05:12:01 PM
do you know , in which kind of MPU Msg , LensID mentioned above is sent to CPU ?   

Just found out:


    "03 15"  :   ("PROP_LENS",),
    "03 24"  :   ("PROP_LENS_NAME",),


example:

        { 0x24, 0x23, 0x03, 0x15, 0x01, 0x20, 0x50, 0x10, 0x3a, 0x00, 0x18, 0x00, 0x18, 0x81, 0x47, 0x92, 0x7e, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xf1, 0x82, 0x01, 0x00, 0x02, 0x07, 0x21, 0x00, 0x00 },/* reply #12.9 */
        { 0x18, 0x17, 0x03, 0x24, 0x45, 0x46, 0x2d, 0x53, 0x32, 0x34, 0x6d, 0x6d, 0x20, 0x66, 0x2f, 0x32, 0x2e, 0x38, 0x20, 0x53, 0x54, 0x4d, 0x00, 0x00 },/* reply #12.3 */


(see PROP_LENS in lens.c for decoding)

Also collected most of the spells into extract_init_spells.py (also exported to known_spells.h)

leegong

@a1ex ,
MPU reports Lens status in Msg09 05 to CPU , 4 bytes in Msg09 05 payload,
the last one is probablly ERCD of Lens communication :
0x00 : good
0x02 : no 0xAA response from Lens after sending Lens CMD 0xA
0x20 : Lens-Camera RTX timeout 
Any info of Msg09 05 on CPU side ?

EDIT :
0x1 looks like that lens is detached.
0x80 is very special , maybe Lens in debug mode.

leegong

@a1ex ,
Data payload inside Msg09 02 is same as that of Msg09 05 , status of AF , Aperture
and IS (motor) in Lens and  ERCD of Lens communication.
Msg09 0A is strongly related to "lv ae".
Msg05 02 is "release data"
Msg05 03 is "release after data"
Msg05 05 is "bulb end"

a1ex

Found out where MPU properties are handled - they are forwarded to PropMgr (which makes the analysis a bit difficult, as they are not handled in sync with mpu_recv messages). However, you can place two logging hooks directly in PropMgr state object code:

- mpu_analyze_recv_data_log: string "NO AnalyzeMpuReceiveData"
- prop_lookup_maybe_log: string "NOT PROPERTYLIST ID"

These two will match the MPU message to its corresponding property. Example for 550D (enable MPU messages and properties in 550D/debugmsg.gdb):

./run_canon_fw.sh 550D,firmware="boot=0" -d debugmsg -s -S & arm-none-eabi-gdb -x 550D/debugmsg.gdb
...
[MPU] Sending : 08 06 01 23 00 01 00 00
[    INT-36h:ff1bb1e0 ] mpu_recv( 08 06 01 23 00 01 00 )

... after a while, likely after processing other messages ...

[     PropMgr:ff056cb0 ] PropState: (0) --10--> (0)      ff1b712c (x=726cf0 z=72a954 t=14)
[     PropMgr:ff1d85ac ] MPU property: 01 23 00 01 00
[     PropMgr:ff1b66ec ] prop_lookup_maybe 80000020 80000020 724f7c 2


That means MPU message 01 23 is mapped to property 0x80000020. Let's look it up:

./run_canon_fw.sh 550D,firmware="boot=0" -d debugmsg |& grep --text -C 5 80000020
...
[     CtrlSrv:ff1fba44 ] (84:02) copyDataToStorage eventID(0x80000020)Data(1)size(0)
[     CtrlSrv:ff1fcf30 ] (83:03) PROP_CARD1_STATUS[1]
...


The above will only cover properties coming from the MPU (e.g. during startup). Luckily, these can be brute-forced: send all possible messages in the same class and see how the firmware reacts - in most cases it won't crash, but it won't boot the GUI either. It will reveal the matching property ID for most messages.

For properties sent from the main CPU to the MPU (e.g. if a setting is changed from Canon menus or from ML), enable the logging hook for prop_request_change (also in debugmsg.gdb) and explore the menus, writing down the properties triggered in the process.

Documented a bunch of properties with these methods, in the usual place: extract_init_spells.py and exported to known_spells.h.

Cross-checking welcome - it's impossible not to find a few missing or misspelled ones.

a1ex

Quote from: leegong on September 14, 2016, 11:50:01 AM
char msg {0x? , 0xA , 0x8 , flag00 , flag01 , data00 , data01 .......} ;
each bit of flag00 , flag01 indicates a specific type of data paylaod is present in msg0A08 or not ,

500D 111: this happens at FF0A5A20.

Quote
so there are 16 kinds of different data structure , only 13 kinds of  payload type are available in 550D TX19.

These are at FF41C140; payload sizes and handlers are:

id size  handler
0  2     unknown
1  6     tv, tv_range
2  5     av, av_range
3  4     iso
4  4     empty (this field is the picture count at the bottom of the screen; likely handled elsewhere
5  6     unknown
6  7     aeb_count (last byte)
7  3     empty
8  5     focusstatus
9  5     empty
a  5     empty
b  6     focusinfo
c  1     empty
d  0     empty
e  0     empty
f  0     empty


Sizes match the ones from leegong.

a1ex

Please find a script that annotates MPU logs (containing mpu_send and mpu_recv calls). So far, it prints the property name and the GUI event ID, if known.

https://bitbucket.org/hudson/magic-lantern/src/qemu/contrib/qemu/eos/mpu_spells/annotate_mpu_log.py
https://bitbucket.org/hudson/magic-lantern/src/qemu/contrib/qemu/eos/mpu_spells/known_spells.py

The script must be run from the mpu_spells directory, as it imports known_spells.py and also looks in button_codes.h to pick the (model-specific) button codes and names. Or, copy it alongside with these two files if you decide to move it.

Sample output:

45.915.489  **INT-36h*:ff2e4494:00:00: *** mpu_recv(06 05 06 26 01 00)                               ; GMT_GUICMD_PRESS_BUTTON_SOMETHING
45.915.734  **INT-36h*:ff2e4494:00:00: *** mpu_recv(06 05 06 20 01 00)                               ; BGMT_Q
45.923.365     PropMgr:ff122df8:00:00: *** mpu_send(0a 08 09 1a 00 00 00 00 00)                      ; PROP 8005002A
45.924.215     PropMgr:ff122df8:00:00: *** mpu_send(06 05 04 00 00 00)                               ; NotifyGUIEvent
45.924.645  **INT-36h*:ff2e4494:00:00: *** mpu_recv(06 05 06 0a 00 00)                               ; BGMT_UNPRESS_ZOOM_OUT
45.924.844  **INT-36h*:ff2e4494:00:00: *** mpu_recv(06 05 06 09 00 00)                               ; BGMT_UNPRESS_ZOOM_IN
45.925.009  **INT-36h*:ff2e4494:00:00: *** mpu_recv(06 05 04 00 00 01)                               ; NotifyGUIEvent
45.925.637  **INT-36h*:ff2e4494:00:00: *** mpu_recv(08 06 01 0b 00 00 00)                            ; PROP_AEB
45.928.221     PropMgr:ff122df8:00:00: *** mpu_send(08 06 00 00 04 00 00)                            ; Complete WaitID = NotifyGUIEvent
45.931.410     PropMgr:ff122df8:00:00: *** mpu_send(06 05 03 34 00 00)                               ; PROP_Q_POSITION

leegong

@a1ex:
Upon receiving Msg08 02 , MPU gets function code in payload of Msg , which is 0 - 0x7F in 550D ,
each  function code stands for one kind of specific action or operation on MPS side :
function code 0xF    : send lens custom CMD
function code 0x10  : maybe drive lens focus motor 
function code 0x48  : read current Lens data   
function code 0x60  : calculate checksum of FW on MPU side
function code 0x68  : fresh current unknown temperature
function code 0x6B  : get current PROP_EFIC_TEMP and stores it into eeprom.
 

a1ex

That sounds useful; I should probably resume the MPU emulation experiments (if only to learn how to read MIPS code).

Any idea where this might be used in Canon code? Tried to grep for this command in my logs with MPU messages, but found nothing.