1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
This file describes the API between userui_core and a userui plugin (eg,
userui_text). It does not cover the kernel API, which is detailed in the file
KERNEL_API. You want to read this file if you plan to write your own user
interface.
Function API
------------
Each userui module should define a struct userui_ops describing its operations,
and also define a pointer to it called "userui_ops". See userui_skeleton.c for
an example. The userui_ops struct defined for your module must contain the
following elements :
char *name;
void (*prepare) ();
void (*cleanup) ();
void (*message) (unsigned long type, unsigned long level, int normally_logged, char *text);
void (*update_progress) (unsigned long value, unsigned long maximum, char *text);
void (*log_level_change) ();
void (*redraw) ();
void (*keypress) (int key);
And some optional ones:
unsigned long (*memory_required) ();
char *optstring;
struct option *longopts;
int (*option_handler) (char c);
char *(*cmdline_options) ();
Each element in turn is described below:
char *name;
This is a short string identifying your module.
void prepare()
This function is the first to be called in your module. It is run pretty soon
after the suspend cycle has started. This is where you do all your setup -
this entails opening and reading all the files you will need, allocating all
the memory you will need and anything else to avoid touching the filesystem
once suspending has started. Hibernating will not proceed until this function
exits. If you really need to abort the suspend process because something
failed (not really recommended), you can send a USERUI_MSG_ABORT. This is
described in Communicating with TuxOnIce.
void cleanup()
This is called after the suspend has completed (either through resuming or
aborting). It is expected to clean up things like the console and undo any
effects of prepare() that would otherwise persist.
void message(type, level, normally_logged, text)
This function is called by TuxOnIce when it wishes to update the message
on the screen. FIXME ... fill in details of parameters!
void update_progress(value, maximum, text)
This function is called by TuxOnIce to update progress of suspending or
resuming. The text parameter specifies the text to display in the middle of the
progress bar.
void log_level_change()
Notifies the UI module that the kernel loglevel (given in console_loglevel)
has changed - it may wish to update the display to give more or less
verbosity as required.
void redraw()
Upon resuming, immediately after copying the original kernel back, video memory
is normally filled with old boot messages that need to be cleared. This function
is called to clear and redraw the screen from scratch.
void keypress(int key)
If the user presses a key whilst suspending, this function is called with the
appropriate keycode.
The following functions are optional:
unsigned long memory_required()
If the process will require a given amount of memory for suspending, that has
not yet been allocated, it can specify an amount here (in bytes).
char *optstring
If the userui module wishes to accept extra command-line options, it can
specify a string of characters here (getopt-style). Module authors should
verify that it does not clash with existing options in handle_params() in
userui_core.c.
struct option *longopts
If the userui module wishes to accept long-style command-line options, it can
specify a pointer to an empty-terminated array of struct option's.
int option_handler(char c)
If not NULL, this function is called when command-line options are found that
the userui_core could not handle. If the module handles the given option,
then it should return 1. If not, it should return 0.
char *cmdline_options()
This function should returns a string containing the usage text for the extra
options provided by this module.
Communicating with TuxOnIce
---------------------------
Most of the messages are handled by userui_core, but there may arise occasions
where you wish to manipulate TuxOnIce directly. This can be achieved by
using the send_message function:
int send_message(int type, void* buf, int len);
This function returns 1 on success (the message was successfully sent to the
kernel) or 0 on failure. Some messages of interest are:
type = USERUI_MSG_ABORT (no parameters)
Aborts the current suspend cycle (eg because the user pressed Escape).
type = USERUI_MSG_SET_STATE, buf = &suspend_action, len = sizeof(int)
Sets the suspend_action variable to the given value. This allows you to
change the following flags: SUSPEND_REBOOT, SUSPEND_PAUSE, SUSPEND_SLOW,
SUSPEND_LOGALL, SUSPEND_SINGLESTEP, SUSPEND_PAUSE_NEAR_PAGESET_END.
type = USERUI_MSG_GET_STATE (no parameters)
This will tell the kernel to reply with the current suspend_action value.
You should call this after a call to USERUI_MSG_SET_STATE to ensure the
kernel and userspace are in sync.
type = USERUI_MSG_SET_LOGLEVEL, buf = &new_loglevel, len = sizeof(int)
Sets the console loglevel to the given value.
type = USERUI_MSG_GET_LOGLEVEL, buf = &new_loglevel, len = sizeof(int)
Gets the current console loglevel, and calls the log_level_change function
to report it.
Restrictions on your userui module
----------------------------------
Memory Allocation and Usage
- it shouldn't use too much. All memory of the userui is mlock()'d so it is
not swapped out to disk. It shouldn't try to allocate huge amounts of memory
outside of your prepare() function as this will starve TuxOnIce of
memory for IO. A resource limit is enforced while suspending so excessive
allocations should hopefully return with ENOMEM, but you should avoid this
in the first place.
Disk access
- Big no no. Do *NOT* try to access the disk whilst suspending as this will
most likely corrupt the suspend image. Resource limits should cause file
opening attempts to fail. If you want to opening a /proc entry or something
not linked to a disk, do it in prepare().
Forking or threading
- Don't fork mid-suspend. Resource limits will probably ensure that it fails.
You can create forks or threads in prepare(). It should be safe so long as
all threads follow these same rules.
Exiting
- Exiting before the suspend/resume cycle has finished may corrupt the image.
Don't try it. Signal handlers are installed to catch most common signals and
simply sleep the process for a while.
Certain syscalls
- It has been noted that calling select() or poll() to wait for data on a
socket can be detrimental to suspending (causing things like several-second
hangs whilst "Eating memory").
Minimalism is good - the process shouldn't do too much other than play with its
own memory, respond to events and dump stuff to display.
|