Trying to understand GUI events on the 550D.
gui_main_task[]
NSTUB( 0xFF01FF94, gui_main_task )
This retrieves events from the main message queue (see GUI Events) and calls a function from a jump table with 8 elements:
// ff020760: GUI_CONTROLQueueClear// ff020878: gui_main_loop_bottom // sub_FF02090C // ff020968: guiother_cancel_all_event // ff0209f4: sub_FF0209F4 // ff0209fc: j_handleGuiInit // ff020a04: gui_change_shoot_type // ff020a2c: gui_change_lcd_state
Event types are 0-7:
- 0 = GUI control (includes button presses)
- 1 = ?
- 2 = ?
- 3 = cancel other events?
- 4 = shutter-related? also required for card detection?
- 5 = IDLEHandler
- 6 = GUI_CHANGE_SHOOT_TYPE
- 7 = GUI_CHANGE_LCD_STATE
The event struct from 5D2 seems to be used, too (not sure whether the fields are the same).
event->type event->param event->obj event->arg
GUI_CONTROL[]
It calls GUI_Control_Post(arg,obj,param). Sometimes it logs the event with DebugMsg.
If the event queue is clear; if yes, it returns. Not the normal path execution code. In some IDCs it is named QueueClear.
GUI_Control_Post / gui_massive_event_loop[]
This is a huge case statement, where codes like 0x830 are generated (and passed to CtrlSrv_try_post_something).
Many button press events have arg=0. In this case, code arrives at this jump table:
FF0932B0: 908ff104 addls pc, pc, r4, lsl #2
For PRESS_INFO_BUTTON, p=00000007 and index is 8. Similar for SET and MENU, maybe for others.
IDLEHandler[]
From handleGuiInit, code arrives at IDLEHandler, where is a huge case statement.
IDLEHandler can be decompiled by GPL Tools/ARM console (but it's not done by default, because the function is too big). Result is huge (2400 lines), so it's better to save it to a file.
In [10]: d = deco.decompile(0xFF214D24) In [11]: f = open("IDLEHandler.txt","w") In [12]: print >> f, d In [13]: f.close()
Also, let's try to guess how many arguments it has:
In [14]: funargs.getFuncSignature(0xFF214D24) int IDLEHandler(arg0, arg1, arg2, arg3);
IDLEHandler tests if arg1 is equal to various constants:
0x807: PRESS_RIGHT_BUTTON 0x809: PRESS_LEFT_BUTTON 0x80b: PRESS_UP_BUTTON 0x80d: PRESS_DOWN_BUTTON 0x80f: PRESS_MENU_BUTTON 0x829: PRESS_INFO_BUTTON 0x83A: PRESS_INDIAL_UP_BUTTON 0x83C: PRESS_INDIAL_RIGHT_BUTTON 0x83E: PRESS_INDIAL_DOWN_BUTTON 0x840: PRESS_INDIAL_LEFT_BUTTON 0x812: PRESS_SET_BUTTON 0x800: GOT_TOP_OF_CONTROL 0x802: INITIALIZE_CONTROLLER 0x10000000: PRESS_DISP_BUTTON 0x10000003: PICTURE_STYLE or PROTECTMIC BUTTON 0x10000019: START_MENU_WB_MODE 0x10000083: LOCAL_AEMODE_CHECK 0x1000008c: LOCAL_MOVIE_RECORD_STOP 0x1000009d: OTHER_NOTIFY_JOB_STATE ...
Some codes missed by the decompiler (because it does not handle jump tables):
PRESS_UNAVI_BUTTON PRESS_SW1_BUTTON UNPRESS_SW1_BUTTON PRESS_SW2_BUTTON UNPRESS_SW2_BUTTON PRESS_LV_MOVIE_START_BUTTON
How it's called?[]
Excerpts from the HTML output of GPL Tools/ARM console:
handleGuiInit+444: create_idleHandler_task() create_idleHandler_task+12: gui_task_create(@IDLEHandler, 0) gui_task_create+140: ctrlman_dispatch_event(ret_new_task_struct_FF2B4C24 /* points to arg0 */ , 0x802, 0, 0) ctrlman_dispatch_event+96: FUNC(*(arg0))(*(4 + arg0), arg1, arg2, arg3) => ret_FUNC(*(arg0))_FF2B4B20
Other ctrlman calls:
gui_task_create+140: ctrlman_dispatch_event(ret_new_task_struct_FF2B4C24 /* points to arg0 */ , 0x802, 0, 0) gui_task_destroy+204: ctrlman_dispatch_event(0, 0x800, 0, 0) sub_FF2B4FE8+88: ctrlman_dispatch_event(*(0x1e640), arg1, arg2, arg3) sub_FF2B50A8+20: ctrlman_dispatch_event(arg0, 0x801, 0, 0) sub_FF2B50A8+44: ctrlman_dispatch_event(arg1, 0x800, 0, 0)
Hint: ctrlman_dispatch_event can be used to send events to gui tasks (like ML menu task or IDLEHandler task):
void send_event_to_IDLEHandler(int event) { ctrlman_dispatch_event((void*)GMT_IDLEHANDLER_TASK, event, 0, 0); }
void menu_send_event(int event) { ctrlman_dispatch_event(gui_menu_task, event, 0, 0); }
StartPlayMain_handler[]
This is another huge case statement, for the Play dialog.
UNPRESS_TELE_MAG_BUTTON UNPRESS_WIDE_REDUCTION_BUTTON
Event dump[]
[MAGIC] EVENT: 0 f=ff020760 p=0000003f o=00000000 a=00000000 [GUI] IDLEHandler PRESS_SW1_BUTTON
[MAGIC] EVENT: 0 f=ff020760 p=00000040 o=00000000 a=00000000 [GUI] IDLEHandler UNPRESS_SW1_BUTTON
[MAGIC] EVENT: 0 f=ff020760 p=00000007 o=00000000 a=00000000 [GUI] GuiMainEventHandler.c PRESS_INFO_BUTTON // that's Disp
Indy: check [GUI_E] debug messages ?
990: 832.667 [GUI_E] GUI_Control:74 0x0 991: 832.821 [GUI_M] GUICMD_LOCK_ON ... 997: 836.476 [GUI_E] GUI_Control:76 0x0 998: 836.691 [BIND] bindReceiveSwitch (19, 0) 999: 836.947 [GUI_M] GUICMD_CLOSE_SLOT_COVER
Press/unpress parameter codes for event 0, as received by gui_main_task_550d:
1c/1d = left 1e/1f = up 1a/1b = right 20/21 = down 4/5 = set3 = wheel right, 2 = wheel left7 = disp 6 = menu 8 = direct print (it might be the Q button) 3f/40 = half shutter 56 = iso button? (a=10)d/e = star button (zoom out)b/c = zoom in button(manual mode only?) a = trash mode switch also generates p=56, with a=9, e, 15, 7, charge battery pack.
Wanted: missing unpress codes.
Event codes (hex), as received by menu_handler in menu.c (enable debug.draw-event to see them on the screen):
Play 10000000 Q 10000005 AV 100000b5?! Zoom in/out 10000048/49; depressing zoom in also generates an 81a ISO 100000b5?! LiveView 1000000d DOF preview 10000048/49 Flash 100000a6? Flash Off 100000a6? LCD sensor 100000a6? Mode Dial 100000a6? Power Off 100000cb/cc Power On 100000cd Disp (info) 829 Up 80b/c Down 80d/e Right 807/8 Left 809/a Set 812/3 Menu ??? Shutter Half 48/49 and then b5 Shutter Full ???
So, either 10000a6 and 10000b5 are some groups of events, or they are other kind of events triggered by those button presses (and overwrite the display too fast for me to see them).
Some interesting codes are at *(arg3).
Event 100000a6, *(arg3):
8000003d - timer? 8005001f - timer? 80050007 - timer? 80030014 - timer? 80020010 - LCD sensor 80000005 - flash on/off, wheel? 80030014 - wheel left? 80000004 - change focus mode between AF/MF (on the lens) 80030011 - sent when you zoom in/out 80030021 - change lens maybe
Those might be properties changed by this event.
Mode dial generates LOTS of a6 events!
Event 10000048:
*(arg3) is a counter (how many times you pressed the button?!)
Code and discussion[]
- https://bitbucket.org/a1ex/magic-lantern/src/5cefa40dd254/ (gui.c)
- http://groups.google.com/group/ml-devel/browse_thread/thread/8bc3bc952a3a2e16
To be sorted[]
Arm.Indy also found some GUI events and listed them on the Properties page.