mce.h 18 KB
Newer Older
1 2 3 4
/**
 * @file mce.h
 * Generic headers for Mode Control Entity
 * <p>
5 6 7
 * Copyright (c) 2004 - 2011 Nokia Corporation and/or its subsidiary(-ies).
 * Copyright (c) 2012 - 2020 Jolla Ltd.
 * Copyright (c) 2019 - 2020 Open Mobile Platform LLC.
8 9
 * <p>
 * @author David Weinehall <david.weinehall@nokia.com>
10 11 12 13
 * @author Irina Bezruk <ext-irina.bezruk@nokia.com>
 * @author Santtu Lakkala <ext-santtu.1.lakkala@nokia.com>
 * @author Vesa Halttunen <vesa.halttunen@jollamobile.com>
 * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *
 * mce is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * mce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with mce.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef _MCE_H_
#define _MCE_H_

#include "datapipe.h"

/** Indicate enabled (sub)mode */
#define DISABLED_STRING			"yes"
34

35 36 37 38 39 40 41
/** Indicate disabled (sub)mode */
#define ENABLED_STRING			"no"

/* Names of LED patterns */

/** LED pattern used when powering on the device */
#define MCE_LED_PATTERN_POWER_ON		"PatternPowerOn"
42

43 44
/** LED pattern used when powering off the device */
#define MCE_LED_PATTERN_POWER_OFF		"PatternPowerOff"
45

46 47
/** LED pattern used when camera is active */
#define MCE_LED_PATTERN_CAMERA			"PatternWebcamActive"
48

49 50
/** LED pattern used to indicate that the device is on when idle */
#define MCE_LED_PATTERN_DEVICE_ON		"PatternDeviceOn"
51

52 53
/** LED pattern used when charging the battery */
#define MCE_LED_PATTERN_BATTERY_CHARGING	"PatternBatteryCharging"
54

55 56
/** LED pattern used when the battery is full */
#define MCE_LED_PATTERN_BATTERY_FULL		"PatternBatteryFull"
57

58 59 60 61 62
/** Binary LED pattern used by CSD that should always use sw breathing */
#define MCE_LED_PATTERN_CSD_BINARY_BLINK	"PatternCsdLedBlink"

/** Rgb LED pattern used by CSD that should always use sw breathing */
#define MCE_LED_PATTERN_CSD_WHITE_BLINK		"PatternCsdWhiteBlink"
63

64 65
/** LED pattern used when the battery is low */
#define MCE_LED_PATTERN_BATTERY_LOW		"PatternBatteryLow"
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
/** LED pattern used when XXX */
#define MCE_LED_PATTERN_BATTERY_CHARGING_FLAT	"PatternBatteryChargingFlat"

/** LED pattern used by messaging mw */
#define MCE_LED_PATTERN_COMMON_NOTIFICATION	"PatternCommonNotification"

/** LED pattern used by messaging mw */
#define MCE_LED_PATTERN_COMMUNICATION_CALL	"PatternCommunicationCall"

/** LED pattern used by messaging mw */
#define MCE_LED_PATTERN_COMMUNICATION_EMAIL	"PatternCommunicationEmail"

/** LED pattern used by messaging mw */
#define MCE_LED_PATTERN_COMMUNICATION_IM	"PatternCommunicationIM"

/** LED pattern used by messaging mw */
#define MCE_LED_PATTERN_COMMUNICATION_SMS	"PatternCommunicationSMS"

/** LED pattern used by CSD application */
#define MCE_LED_PATTERN_CSD_WHITE		"PatternCsdWhite"

/** LED pattern used when blanking fails due to dbus ipc */
#define MCE_LED_PATTERN_DISPLAY_BLANK_FAILED	"PatternDisplayBlankFailed"

/** LED pattern used when unblanking fails due to dbus ipc */
#define MCE_LED_PATTERN_DISPLAY_UNBLANK_FAILED	"PatternDisplayUnblankFailed"

/** LED pattern used when frame buffer suspend fails */
#define MCE_LED_PATTERN_DISPLAY_SUSPEND_FAILED	"PatternDisplaySuspendFailed"

/** LED pattern used when frame buffer resume fails */
#define MCE_LED_PATTERN_DISPLAY_RESUME_FAILED	"PatternDisplayResumeFailed"

/** LED pattern used when mce kills unresponsive lipstick */
#define MCE_LED_PATTERN_KILLING_LIPSTICK	"PatternKillingLipstick"

/** LED pattern used when display is on, but mce holds touch input */
#define MCE_LED_PATTERN_TOUCH_INPUT_BLOCKED	"PatternTouchInputBlocked"

/** LED pattern used when XXX */
#define MCE_LED_PATTERN_DISPLAY_DIMMED		"PatternDisplayDimmed"

109 110
/** LED pattern used for communication events */
#define MCE_LED_PATTERN_COMMUNICATION_EVENT	"PatternCommunication"
111

112 113 114
/** LED pattern used for communication events when battery is full */
#define MCE_LED_PATTERN_COMMUNICATION_EVENT_BATTERY_FULL	"PatternCommunicationAndBatteryFull"

115 116 117 118 119 120
/** LED pattern used when fingerprint scanner is active */
#define MCE_LED_PATTERN_SCANNING_FINGERPRINT	"PatternScanningFingerprint"

/** LED pattern used when fingerprint acquisition events are seen */
#define MCE_LED_PATTERN_FINGERPRINT_ACQUIRED	"PatternFingerprintAcquired"

121 122 123 124 125 126 127 128 129
/** LED pattern used when proximity sensor is covered */
#define MCE_LED_PATTERN_PROXIMITY_COVERED	"PatternProximityCovered"

/** LED pattern used during proximity sensor uncover hysteresis */
#define MCE_LED_PATTERN_PROXIMITY_UNCOVERING	"PatternProximityUncovering"

/** LED pattern used when proximity sensor is uncovered */
#define MCE_LED_PATTERN_PROXIMITY_UNCOVERED	"PatternProximityUncovered"

130
/** Persistent lock file for backups */
Santtu Lakkala's avatar
Santtu Lakkala committed
131
#define MCE_SETTINGS_LOCK_FILE_PATH		G_STRINGIFY(MCE_RUN_DIR) "/restored"
132

133 134
/** Path for system MALF state indicator file */
#define MALF_FILENAME				"/var/malf"
135

136 137
/** Path for MCE MALF state indicator file */
#define MCE_MALF_FILENAME			G_STRINGIFY(MCE_RUN_DIR) "/malf"
138 139 140

/** Module information */
typedef struct {
141
	/** Name of the module */
142
	const gchar *const name;
143 144

	/** Module dependencies */
145
	const gchar *const *const depends;
146 147

	/** Module recommends */
148
	const gchar *const *const recommends;
149 150

	/** Module provides */
151
	const gchar *const *const provides;
152 153

	/** Module provides */
154
	const gchar *const *const enhances;
155 156

	/** Module conflicts */
157
	const gchar *const *const conflicts;
158 159

	/** Module replaces */
160
	const gchar *const *const replaces;
161 162 163 164 165

	/** Module priority:
	 * lower value == higher priority
	 * This value is only used when modules conflict
	 */
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
	const gint priority;
} module_info_struct;

/** Used for invalid translations and values */
#define MCE_INVALID_TRANSLATION		-1

/** Alarm UI states; integer representations */
typedef enum {
	/** Alarm UI state not valid */
	MCE_ALARM_UI_INVALID_INT32 = MCE_INVALID_TRANSLATION,
	/** Alarm UI not visible */
	MCE_ALARM_UI_OFF_INT32 = 0,
	/** Alarm UI visible and ringing */
	MCE_ALARM_UI_RINGING_INT32 = 1,
	/** Alarm UI visible but not ringing */
	MCE_ALARM_UI_VISIBLE_INT32 = 2,
} alarm_ui_state_t;

184 185
const char *alarm_state_repr(alarm_ui_state_t state);

186
/** System sub-modes; several of these can be active at once */
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
typedef enum {
	/** Submode invalid */
	MCE_SUBMODE_INVALID		= (1 << 31),
	/** No submodes enabled */
	MCE_SUBMODE_NORMAL		= 0,
	/** Touchscreen/Keypad lock enabled */
	MCE_SUBMODE_TKLOCK		= (1 << 0),
	/** Event eater enabled */
	MCE_SUBMODE_EVEATER		= (1 << 1),
	/** Bootup in progress */
	MCE_SUBMODE_BOOTUP		= (1 << 3),
	/** State transition in progress */
	MCE_SUBMODE_TRANSITION		= (1 << 4),
	/** Touchscreen/Keypad autorelock active */
	MCE_SUBMODE_AUTORELOCK		= (1 << 5),
	/** Visual Touchscreen/Keypad active */
	MCE_SUBMODE_VISUAL_TKLOCK	= (1 << 6),
	/** Proximity is used to protect from accidental events */
	MCE_SUBMODE_POCKET		= (1 << 7),
	/** Touchscreen/Keypad lock is enabled based on proximity state */
	MCE_SUBMODE_PROXIMITY_TKLOCK	= (1 << 8),
	/** Device is in MALF state */
	MCE_SUBMODE_MALF		= (1 << 9),
} submode_t;
211

212 213 214
const char *submode_change_repr(submode_t prev, submode_t curr);
const char *submode_repr(submode_t submode);

215 216
/** System state */
typedef enum {
217 218 219 220 221 222
	MCE_SYSTEM_STATE_UNDEF    = -1, /**< System state not set */
	MCE_SYSTEM_STATE_SHUTDOWN =  0, /**< System is in shutdown state */
	MCE_SYSTEM_STATE_USER     =  2, /**< System is in user state */
	MCE_SYSTEM_STATE_ACTDEAD  =  5, /**< System is in acting dead state */
	MCE_SYSTEM_STATE_REBOOT   =  6, /**< System is in reboot state */
	MCE_SYSTEM_STATE_BOOT     =  9, /**< System is in bootup state */
223 224
} system_state_t;

225 226
const char *system_state_repr(system_state_t state);

227 228 229 230 231 232 233 234 235 236 237
/** Call state */
typedef enum {
	/** Invalid call state */
	CALL_STATE_INVALID = MCE_INVALID_TRANSLATION,
	/** No call on-going */
	CALL_STATE_NONE = 0,
	/** There's an incoming call ringing */
	CALL_STATE_RINGING = 1,
	/** There's an active call */
	CALL_STATE_ACTIVE = 2,
	/** The device is in service state */
238 239 240
	CALL_STATE_SERVICE = 3,
	/** Ringing call that is ignored by call ui and mce */
	CALL_STATE_IGNORED = 4,
241 242
} call_state_t;

243
const char *call_state_repr(call_state_t state);
244 245
const char *call_state_to_dbus(call_state_t state);
call_state_t call_state_from_dbus(const char *name);
246

247 248 249
/** Call type */
typedef enum {
	/** Invalid call type */
250
	CALL_TYPE_INVALID   = MCE_INVALID_TRANSLATION,
251
	/** The call is a normal call */
252
	CALL_TYPE_NORMAL    = 0,
253
	/** The call is an emergency call */
254
	CALL_TYPE_EMERGENCY = 1
255 256
} call_type_t;

257 258 259
const char *call_type_repr(call_type_t type);
call_type_t call_type_parse(const char *name);

260 261
/** Display state */
typedef enum {
262 263 264 265 266 267 268 269 270 271 272
	MCE_DISPLAY_UNDEF,       /**< Display state not set */
	MCE_DISPLAY_OFF,         /**< Display is off */
	MCE_DISPLAY_LPM_OFF,     /**< Display is off in low power mode */
	MCE_DISPLAY_LPM_ON,      /**< Display is on in low power mode */
	MCE_DISPLAY_DIM,         /**< Display is dimmed */
	MCE_DISPLAY_ON,          /**< Display is on */
	MCE_DISPLAY_POWER_UP,    /**< Display is resuming */
	MCE_DISPLAY_POWER_DOWN,  /**< Display is suspending */

	MCE_DISPLAY_NUMSTATES    /**< Number of display states */

273 274
} display_state_t;

275 276
const char *display_state_repr(display_state_t state);

277 278 279 280 281 282 283
/** Cover state */
typedef enum {
	COVER_UNDEF = -1,		/**< Cover state not set */
	COVER_CLOSED = 0,		/**< Cover is closed */
	COVER_OPEN = 1			/**< Cover is open */
} cover_state_t;

284 285 286
const char *cover_state_repr(cover_state_t state);
const char *proximity_state_repr(cover_state_t state);

287 288 289
/** Lock state */
typedef enum {
	/** Lock state not set */
290
	TKLOCK_REQUEST_UNDEF         = -1,
291
	/** Lock is disabled */
292
	TKLOCK_REQUEST_OFF           =  0,
293
	/** Delayed unlock; write only */
294
	TKLOCK_REQUEST_OFF_DELAYED   =  1,
295
	/** Lock is disabled, but autorelock isn't disabled; write only */
296
	TKLOCK_REQUEST_OFF_PROXIMITY =  2,
297
	/** Lock is enabled */
298
	TKLOCK_REQUEST_ON            =  3,
299
	/** Dimmed lock; write only */
300
	TKLOCK_REQUEST_ON_DIMMED     =  4,
301
	/** Enable proximity lock (no UI); write only */
302
	TKLOCK_REQUEST_ON_PROXIMITY  =  5,
303
	/** Toggle lock state; write only */
304
	TKLOCK_REQUEST_TOGGLE        =  6,
305
	/** Delayed lock; write only */
306 307
	TKLOCK_REQUEST_ON_DELAYED    =  7,
} tklock_request_t;
308

309
const char *tklock_request_repr(tklock_request_t state);
310

311 312
const char *tklock_status_repr(int status);

313 314 315 316 317 318 319 320 321 322 323 324 325
/** Raw udev battery status */
typedef enum
{
    BATTERY_STATE_UNKNOWN,
    BATTERY_STATE_CHARGING,
    BATTERY_STATE_DISCHARGING,
    BATTERY_STATE_NOT_CHARGING,
    BATTERY_STATE_FULL,
} battery_state_t;

const char *battery_state_repr(battery_state_t state);
const char *battery_state_to_dbus(battery_state_t state);

326 327 328 329 330 331 332 333 334
/** Battery status */
typedef enum {
	BATTERY_STATUS_UNDEF = -1,	/**< Battery status not known */
	BATTERY_STATUS_FULL = 0,	/**< Battery full */
	BATTERY_STATUS_OK = 1,		/**< Battery ok */
	BATTERY_STATUS_LOW = 2,		/**< Battery low */
	BATTERY_STATUS_EMPTY = 3,	/**< Battery empty */
} battery_status_t;

335
const char *battery_status_repr(battery_status_t state);
336
const char *battery_status_to_dbus(battery_status_t state);
337

338 339 340 341 342 343 344
/** Charging status */
typedef enum {
	CHARGER_STATE_UNDEF = -1,	/**< Not known yet */
	CHARGER_STATE_OFF   =  0,	/**< Not charging */
	CHARGER_STATE_ON    =  1,	/**< Charging */
} charger_state_t;

345
const char *charger_state_repr(charger_state_t state);
346
const char *charger_state_to_dbus(charger_state_t state);
347

348 349 350 351 352 353 354 355 356 357 358 359 360
/** Known charger types
 *
 * Note that the ordering is:
 *
 * a) significant in the sense that in case there are several chargers
 *    connected and active at the same time, maximum numerical value is
 *    exposed as effective charger type on D-Bus
 *
 * b) internal to mce, so that values can and should be rearranged if
 *    there should be changes in what makes sense to ui side.
 */
typedef enum
{
361 362 363 364 365 366
    /* Placeholder value for lookup failures etc
     */
    CHARGER_TYPE_INVALID,

    /* Value that signifies that no charger is connected
     */
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
    CHARGER_TYPE_NONE,

    /* Charger types that do not carry special meaning from
     * sfos UI point of view.
     */
    CHARGER_TYPE_OTHER,
    CHARGER_TYPE_WIRELESS,
    CHARGER_TYPE_CDP,           // Charging Downstream Port

    /* Wall chargers imply notification on disconnect
     */
    CHARGER_TYPE_DCP,           // Dedicated Charging Port
    CHARGER_TYPE_HVDCP,         // High Voltage DCP

    /* PC connection implies usb mode management
     */
    CHARGER_TYPE_USB,           // Standard Downstream Port
} charger_type_t;

386
charger_type_t charger_type_parse(const char *name);
387 388 389
const char *charger_type_repr(charger_type_t type);
const char *charger_type_to_dbus(charger_type_t type);

390 391 392 393 394 395 396
/** Camera button state */
typedef enum {
	CAMERA_BUTTON_UNDEF = -1,	/**< Camera button state not set */
	CAMERA_BUTTON_UNPRESSED = 0,	/**< Camera button not pressed */
	CAMERA_BUTTON_LAUNCH = 1,	/**< Camera button fully pressed */
} camera_button_state_t;

397 398
const char *camera_button_state_repr(camera_button_state_t state);

399 400 401 402 403 404 405 406 407 408 409 410
/** Audio route */
typedef enum {
	/** Audio route not defined */
	AUDIO_ROUTE_UNDEF = -1,
	/** Audio routed to handset */
	AUDIO_ROUTE_HANDSET = 0,
	/** Audio routed to speaker */
	AUDIO_ROUTE_SPEAKER = 1,
	/** Audio routed to headset */
	AUDIO_ROUTE_HEADSET = 2,
} audio_route_t;

411 412
const char *audio_route_repr(audio_route_t state);

413 414
/** USB cable state */
typedef enum {
415 416 417 418
	USB_CABLE_UNDEF        = -1,	/**< Usb cable state not set */
	USB_CABLE_DISCONNECTED =  0,	/**< Cable is not connected */
	USB_CABLE_CONNECTED    =  1,	/**< Cable is connected */
	USB_CABLE_ASK_USER     =  2,	/**< Ask mode from user */
419 420
} usb_cable_state_t;

421
const char *usb_cable_state_repr(usb_cable_state_t state);
422
const char *usb_cable_state_to_dbus(usb_cable_state_t state);
423

424 425 426 427 428 429 430 431 432 433
/** Thermal status */
typedef enum {
	/** Thermal state not set */
	THERMAL_STATE_UNDEF = -1,
	/** Thermal state ok */
	THERMAL_STATE_OK = 0,
	/** Thermal sensors indicate overheating */
	THERMAL_STATE_OVERHEATED = 1,
} thermal_state_t;

434 435
const char *thermal_state_repr(thermal_state_t state);

436 437
/** Exceptional UI status */
typedef enum {
438 439 440 441 442 443 444
	UIEXCEPTION_TYPE_NONE   = 0,
	UIEXCEPTION_TYPE_LINGER = 1<<0,
	UIEXCEPTION_TYPE_CALL   = 1<<1,
	UIEXCEPTION_TYPE_ALARM  = 1<<2,
	UIEXCEPTION_TYPE_NOTIF  = 1<<3,
	UIEXCEPTION_TYPE_NOANIM = 1<<4,
} uiexception_type_t;
445

446 447
const char *uiexception_type_repr(uiexception_type_t type);
const char *uiexception_type_to_dbus(uiexception_type_t type);
448

449 450
/** D-Bus service availability */
typedef enum {
spiiroin's avatar
spiiroin committed
451 452 453
	SERVICE_STATE_UNDEF   = -1,
	SERVICE_STATE_STOPPED =  0,
	SERVICE_STATE_RUNNING =  1,
454 455 456 457
} service_state_t;

const char *service_state_repr(service_state_t state);

458 459 460 461 462 463 464 465 466 467 468 469 470 471
/** These must match with what sensorfw uses */
typedef enum
{
    MCE_ORIENTATION_UNDEFINED   = 0,  /**< Orientation is unknown. */
    MCE_ORIENTATION_LEFT_UP     = 1,  /**< Device left side is up */
    MCE_ORIENTATION_RIGHT_UP    = 2,  /**< Device right side is up */
    MCE_ORIENTATION_BOTTOM_UP   = 3,  /**< Device bottom is up */
    MCE_ORIENTATION_BOTTOM_DOWN = 4,  /**< Device bottom is down */
    MCE_ORIENTATION_FACE_DOWN   = 5,  /**< Device face is down */
    MCE_ORIENTATION_FACE_UP     = 6,  /**< Device face is up */
} orientation_state_t;

const char *orientation_state_repr(orientation_state_t state);

472 473 474 475 476 477 478 479 480
/** Key pressed/realease state */
typedef enum {
    KEY_STATE_UNDEF    = -1,
    KEY_STATE_RELEASED =  0,
    KEY_STATE_PRESSED  =  1,
} key_state_t;

const char *key_state_repr(key_state_t state);

481 482 483 484 485 486 487 488 489 490
/** Generic "extended boolean" type */
typedef enum
{
  TRISTATE_UNKNOWN = -1,
  TRISTATE_FALSE   =  0,
  TRISTATE_TRUE    =  1,
} tristate_t;

const char *tristate_repr(tristate_t state);

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
/** Fingerprint daemon state */
typedef enum fpstate_t
{
    FPSTATE_UNSET,
    FPSTATE_ENUMERATING,
    FPSTATE_IDLE,
    FPSTATE_ENROLLING,
    FPSTATE_IDENTIFYING,
    FPSTATE_REMOVING,
    FPSTATE_VERIFYING,
    FPSTATE_ABORTING,
    FPSTATE_TERMINATING,
} fpstate_t;

fpstate_t   fpstate_parse(const char *name);
const char *fpstate_repr (fpstate_t state);

508
/* XXX: use HAL */
509

510 511 512 513 514 515 516 517 518 519
/** Does the device have a flicker key? */
extern gboolean has_flicker_key;

/**
 * Default inactivity timeout, in seconds;
 * dim timeout: 30 seconds
 * blank timeout: 3 seconds
 *
 * Used in case the display module doesn't load for some reason
 */
520
#define DEFAULT_INACTIVITY_DELAY	33
521 522 523 524 525

submode_t mce_get_submode_int32(void);
gboolean mce_add_submode_int32(const submode_t submode);
gboolean mce_rem_submode_int32(const submode_t submode);

526
bool mce_in_valgrind_mode(void);
527
bool mce_in_sensortest_mode(void);
528
void mce_abort(void) __attribute__((noreturn));
529
void mce_quit_mainloop(void);
530
void mce_signal_handlers_remove(void);
531

532
#define display_state_get() ({\
533
	gint res = datapipe_get_gint(display_state_curr_pipe);\
534 535
	mce_log(LL_DEBUG, "display_state_curr=%s",\
		display_state_repr(res));\
536 537 538
	res;\
})

539 540 541 542 543 544 545 546 547 548 549 550 551 552
/** Clip integer value to given range
 *
 * @param range_lo minimum value
 * @param range_hi maximum value
 * @param val      value to clip
 *
 * @return val clipped to the range
 */
static inline int
mce_clip_int(int range_lo, int range_hi, int val)
{
	return val < range_lo ? range_lo : val > range_hi ? range_hi : val;
}

553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
/** Translate integer value from one range to another
 *
 * Linear conversion of a value in [src_lo, src_hi] range
 * to [dst_lo, dst_hi] range.
 *
 * Uses rounding, so that 55 [0,100] -> 6 [0, 10].
 *
 * @param src_lo lower bound for source range
 * @param src_hi upper bound for source range
 * @param dst_lo lower bound for destination range
 * @param dst_hi upper bound for destination range
 * @param val    value in source range to be translated
 *
 * @return input value mapped to destination range
 */
static inline int
mce_xlat_int(int src_lo, int src_hi, int dst_lo, int dst_hi, int val)
{
571 572 573 574
	/* Deal with empty ranges first; assume that the
	 * low bound is sanest choise available */
	if( src_lo >= src_hi || dst_lo >= dst_hi )
		return dst_lo;
575

576 577
	int src_range = src_hi - src_lo;
	int dst_range = dst_hi - dst_lo;
578

579 580 581
	val -= src_lo;
	val = (val * dst_range + src_range / 2) / src_range;
	val += dst_lo;
582

583
	return mce_clip_int(dst_lo, dst_hi, val);
584 585
}

586
#endif /* _MCE_H_ */