FreeCalypso > hg > leo2moko-debug
diff chipsetsw/drivers/drv_app/kpd/kpd_process_internal_msg.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chipsetsw/drivers/drv_app/kpd/kpd_process_internal_msg.c Mon Jun 01 03:24:05 2015 +0000 @@ -0,0 +1,632 @@ +/** + * @file kpd_process_internal_msg.c + * + * Implementation of Keypad functions. + * These functions implement the keypad processing for all the messages the + * keypad task can receive. + * + * @author Laurent Sollier (l-sollier@ti.com) + * @version 0.1 + */ + +/* + * History: + * + * Date Author Modification + * ---------------------------------------- + * 10/10/2001 L Sollier Create + * + * + * (C) Copyright 2001 by Texas Instruments Incorporated, All Rights Reserved + */ + +#include "kpd/kpd_api.h" +#include "kpd/kpd_env.h" +#include "kpd/kpd_i.h" +#include "kpd/kpd_virtual_key_table_mgt.h" +#include "kpd/kpd_physical_key_def.h" + +#include "rvf/rvf_api.h" +#include "rvm/rvm_use_id_list.h" + +#include <string.h> + +/* External declaration */ +extern T_KPD_ENV_CTRL_BLK* kpd_env_ctrl_blk; + + +/* Definition of the wait time in the loop */ +#ifdef _WINDOWS + #define WAIT_TIME_LOOP (50) +#else + #define WAIT_TIME_LOOP (10) +#endif + + +/* This structure gathers informations about one physical key Id. + It define if subscriber is notified for this physical key */ +typedef struct { UINT32 subscriber_mask; + } T_PHYSICAL_KEY_MASK; + + +/** Definition of a set of keys with repeat keys parameters. */ +typedef struct { UINT8 nb_notified_keys; + UINT16 long_press_time; /* in ms */ + UINT16 repeat_time; /* in ms */ + T_KPD_NOTIF_LEVEL notif_level[KPD_NB_PHYSICAL_KEYS]; + } T_PHYSICAL_KEY_PARAM_TABLE; + + +/* This structure gather general informations about subscriber id */ +typedef struct { T_RV_RETURN return_path; + T_KPD_MODE mode; + T_PHYSICAL_KEY_PARAM_TABLE notified_keys; + } T_SUBSCRIBER_INFOS; + + +/* Informations for all the physical keys Id. + This variable is updated each time a client subscribe to the keypad driver, + unsubscribe, or change notification key level. + Warn that position of the physical key Id is implicit cause of the rule + used to define the vpm table */ +static T_PHYSICAL_KEY_MASK physical_key_mask[KPD_NB_PHYSICAL_KEYS] = {0}; + +/* Informations for all the subscribers */ +static T_SUBSCRIBER_INFOS* subscriber_infos[KPD_MAX_SUBSCRIBER] = {0}; + + + +/** + * @name Functions implementation + * + */ +/*@{*/ + +/** + * function: kpd_return_path_already_defined + */ +static BOOL kpd_return_path_already_defined(T_RV_RETURN return_path) +{ + UINT8 i; + BOOL ret = FALSE; + + for (i = 0; i < KPD_MAX_SUBSCRIBER; i++) + if ( subscriber_infos[i] != 0 ) + if (subscriber_infos[i]->return_path.callback_func != 0) + { + if (subscriber_infos[i]->return_path.callback_func == return_path.callback_func) + { + ret = TRUE; + break; + } + } + else + { + if (subscriber_infos[i]->return_path.addr_id == return_path.addr_id) + { + ret = TRUE; + break; + } + } + + return ret; +} + +/** + * function: kpd_subscribe_i + */ +T_RV_RET kpd_subscribe_i(T_SUBSCRIBER_ID subscriber_id, + T_KPD_MODE mode, + T_KPD_VIRTUAL_KEY_TABLE* notified_keys, + T_RV_RETURN return_path) +{ + INT8 i, position; + T_RVF_MB_STATUS mb_status; + T_RV_RET ret; + + /* Check the validity of the key table */ + ret = kpd_check_key_table(notified_keys, mode); + + if (ret != RV_OK) + { + /* Remove subscriber id because id was reserved */ + kpd_remove_subscriber(subscriber_id); + + /* Send error message */ + kpd_send_status_message(KPD_SUBSCRIBE_OP, KPD_ERR_KEYS_TABLE, return_path); + } + else + { + if (kpd_return_path_already_defined(return_path) == TRUE) + { + /* Remove subscriber id because id was reserved */ + kpd_remove_subscriber(subscriber_id); + + /* Send error message */ + kpd_send_status_message(KPD_SUBSCRIBE_OP, KPD_ERR_RETURN_PATH_EXISTING, return_path); + + ret = RV_INVALID_PARAMETER; + } + else + { + /* Update subscriber informations */ + /* ------------------------------ */ + + /* Reserve memory for subscriber informations */ + mb_status = rvf_get_buf (kpd_env_ctrl_blk->prim_id, + sizeof(T_SUBSCRIBER_INFOS), + (void **) &subscriber_infos[subscriber_id]); + + if (mb_status != RVF_RED) /* Memory allocation success */ + { + /* Initialize structure */ + memset(subscriber_infos[subscriber_id], 0, sizeof(T_SUBSCRIBER_INFOS)); + + /* Fill the subscriber structure */ + subscriber_infos[subscriber_id]->mode = mode; + subscriber_infos[subscriber_id]->return_path = return_path; + subscriber_infos[subscriber_id]->notified_keys.nb_notified_keys = notified_keys->nb_notified_keys; + subscriber_infos[subscriber_id]->notified_keys.long_press_time = 0; + subscriber_infos[subscriber_id]->notified_keys.repeat_time = 0; + for (i = 0; i < notified_keys->nb_notified_keys; i++) + { + /* Retrieve physical key Id from virtual key_id */ + kpd_retrieve_virtual_key_position( notified_keys->notified_keys[i], + mode, + &position); + + subscriber_infos[subscriber_id]->notified_keys.notif_level[position] = KPD_RELEASE_NOTIF; + } + + /* Update link (ID <-> key) */ + /* ------------------------ */ + for (i = 0; i < notified_keys->nb_notified_keys; i++) + { + /* Retrieve position in vpm table */ + kpd_retrieve_virtual_key_position(notified_keys->notified_keys[i], + mode, + &position); + + /* Update subscriber mask for the physical key */ + physical_key_mask[position].subscriber_mask |= (1<<subscriber_id); + + } + + /* Send success message to suscriber */ + kpd_send_status_message(KPD_SUBSCRIBE_OP, KPD_PROCESS_OK, return_path); + } + else + { + KPD_SEND_TRACE("KPD: Memory allocation error", RV_TRACE_LEVEL_ERROR); + + /* Remove subscriber id because id was reserved */ + kpd_remove_subscriber(subscriber_id); + + /* Send error message to suscriber */ + kpd_send_status_message(KPD_SUBSCRIBE_OP, KPD_ERR_INTERNAL, return_path); + } + } + } + + return RV_OK; +} + + +/** + * function: kpd_unsubscribe_i + */ +T_RV_RET kpd_unsubscribe_i(T_SUBSCRIBER_ID subscriber_id) +{ + UINT8 i; + + /* Delete subscriber informations */ + rvf_free_buf(subscriber_infos[subscriber_id]); + subscriber_infos[subscriber_id] = 0; + + /* Delete link (ID <-> key) */ + for (i = 0; i < KPD_NB_PHYSICAL_KEYS; i++) + { + physical_key_mask[i].subscriber_mask &= ~(1<<subscriber_id); + } + + /* If the subscriber is the keypad owner, this privilege is unset */ + if (kpd_is_owner_keypad(subscriber_id) == TRUE) + kpd_set_keypad_mode(MN_MODE); + + return RV_OK; +} + + +/** + * function: kpd_define_key_notification_i + */ +T_RV_RET kpd_define_key_notification_i(T_SUBSCRIBER_ID subscriber_id, + T_KPD_VIRTUAL_KEY_TABLE* notif_key_table, + T_KPD_NOTIF_LEVEL notif_level, + UINT16 long_press_time, + UINT16 repeat_time) +{ + T_RV_RET ret = RV_OK; + UINT8 i; + INT8 position; + + /* Check the validity of the key table */ + ret = kpd_check_key_table(notif_key_table, subscriber_infos[subscriber_id]->mode); + + if (ret != RV_OK) + { + /* Send error message */ + kpd_send_status_message(KPD_REPEAT_KEYS_OP, KPD_ERR_KEYS_TABLE, subscriber_infos[subscriber_id]->return_path); + + } + else + { + /* Update subscriber informations */ + /* ------------------------------ */ + subscriber_infos[subscriber_id]->notified_keys.long_press_time = long_press_time*100; + subscriber_infos[subscriber_id]->notified_keys.repeat_time = repeat_time*100; + + for (i = 0; i < notif_key_table->nb_notified_keys; i++) + { + /* Retrieve physical key Id from virtual key_id */ + kpd_retrieve_virtual_key_position( notif_key_table->notified_keys[i], + subscriber_infos[subscriber_id]->mode, + &position); + + /* Check if subscriber have asked notification for this key at subscription */ + if ( physical_key_mask[position].subscriber_mask & (1<<subscriber_id) ) + subscriber_infos[subscriber_id]->notified_keys.notif_level[position] = notif_level; + } + + /* Send success message to suscriber */ + kpd_send_status_message(KPD_REPEAT_KEYS_OP, KPD_PROCESS_OK, subscriber_infos[subscriber_id]->return_path); + } + + return ret; +} + + +/** + * function: kpd_change_mode_i + */ +T_RV_RET kpd_change_mode_i(T_SUBSCRIBER_ID subscriber_id, + T_KPD_VIRTUAL_KEY_TABLE* notified_keys, + T_KPD_MODE new_mode) +{ + UINT8 i; + INT8 position; + T_RV_RET ret; + + /* Check the validity of the key table */ + ret = kpd_check_key_table(notified_keys, new_mode); + + if (ret != RV_OK) + { + /* Send error message */ + kpd_send_status_message(KPD_CHANGE_MODE_OP, KPD_ERR_KEYS_TABLE, subscriber_infos[subscriber_id]->return_path); + } + else + { + /* Delete link (ID <-> key) for old mode*/ + for (i = 0; i < KPD_NB_PHYSICAL_KEYS; i++) + { + physical_key_mask[i].subscriber_mask &= ~(1<<subscriber_id); + subscriber_infos[subscriber_id]->notified_keys.notif_level[i] = KPD_NO_NOTIF; + } + + /* Update subscriber structure */ + subscriber_infos[subscriber_id]->mode = new_mode; + subscriber_infos[subscriber_id]->notified_keys.nb_notified_keys = notified_keys->nb_notified_keys; + subscriber_infos[subscriber_id]->notified_keys.long_press_time = 0; + subscriber_infos[subscriber_id]->notified_keys.repeat_time = 0; + for (i = 0; i < notified_keys->nb_notified_keys; i++) + { + /* Retrieve physical key Id from virtual key_id */ + kpd_retrieve_virtual_key_position( notified_keys->notified_keys[i], + new_mode, + &position); + + subscriber_infos[subscriber_id]->notified_keys.notif_level[position] = KPD_RELEASE_NOTIF; + + /* Update link (ID <-> key) for new mode */ + physical_key_mask[position].subscriber_mask |= (1<<subscriber_id); + } + + /* If the subscriber is the keypad owner, this privilege is unset */ + if (kpd_is_owner_keypad(subscriber_id) == TRUE) + kpd_set_keypad_mode(MN_MODE); + + /* Send success message to suscriber */ + kpd_send_status_message(KPD_CHANGE_MODE_OP, KPD_PROCESS_OK, subscriber_infos[subscriber_id]->return_path); + } + + return RV_OK; +} + +/** + * function: kpd_own_keypad_i + */ +T_RV_RET kpd_own_keypad_i(T_SUBSCRIBER_ID subscriber_id, + BOOL is_keypad_owner, + T_KPD_VIRTUAL_KEY_TABLE* keys_owner) +{ + INT8 position; + UINT8 i; + + if (is_keypad_owner == FALSE) + { + /* Check if subscriber Id own the keypad */ + if (kpd_is_owner_keypad(subscriber_id)) + { + kpd_set_keypad_mode(MN_MODE); + + /* Send success message to suscriber */ + kpd_send_status_message(KPD_OWN_KEYPAD_OP, KPD_PROCESS_OK, subscriber_infos[subscriber_id]->return_path); + + } + else + kpd_send_status_message(KPD_OWN_KEYPAD_OP, KPD_ERR_ID_OWNER_KEYPAD, subscriber_infos[subscriber_id]->return_path); + } + else + { + /* Check if keypad driver is already in single-notified mode */ + if (kpd_get_keypad_mode() == SN_MODE) + { + /* Send error message to suscriber */ + kpd_send_status_message(KPD_OWN_KEYPAD_OP, KPD_ERR_SN_MODE, subscriber_infos[subscriber_id]->return_path); + } + else + { + /* Check if all the keys defined in keys_owner are notified to the subsciber */ + for (i = 0; i < keys_owner->nb_notified_keys; i++) + { + /* Retrieve physical key Id from virtual key_id */ + kpd_retrieve_virtual_key_position( keys_owner->notified_keys[i], + subscriber_infos[subscriber_id]->mode, + &position); + + if ( subscriber_infos[subscriber_id]->notified_keys.notif_level == KPD_NO_NOTIF ) + { + /* Send error message to suscriber */ + kpd_send_status_message(KPD_OWN_KEYPAD_OP, KPD_ERR_KEYS_TABLE, subscriber_infos[subscriber_id]->return_path); + return RV_INTERNAL_ERR; + } + } + + /* Set keypad driver in single-notified mode */ + kpd_set_keypad_mode(SN_MODE); + + /* Set owner keypad Id */ + kpd_set_owner_keypad_id(subscriber_id); + + /* Set list of keys used by the keypad owner. Thsi list is is a sub-list + of the keys defined at subscription. For these keys, the keypad owner will + be the only notified. */ + kpd_set_keys_in_sn_mode(keys_owner, subscriber_infos[subscriber_id]->mode); + + /* Send success message to suscriber */ + kpd_send_status_message(KPD_OWN_KEYPAD_OP, KPD_PROCESS_OK, subscriber_infos[subscriber_id]->return_path); + } + } + + return RV_OK; +} + +/** + * function: kpd_set_key_config_i + */ +T_RV_RET kpd_set_key_config_i(T_SUBSCRIBER_ID subscriber_id, + T_KPD_VIRTUAL_KEY_TABLE* reference_keys, + T_KPD_VIRTUAL_KEY_TABLE* new_keys) +{ +#ifdef KPD_MODE_CONFIG + UINT8 i; + + /* Check if some subscriber use the configurable mode */ + for (i = 0; i < KPD_MAX_SUBSCRIBER; i++) + { + if ( (subscriber_infos[i] != 0) && (subscriber_infos[i]->mode == KPD_MODE_CONFIG) ) + { + /* Send error message to suscriber */ + kpd_send_status_message(KPD_SET_CONFIG_MODE_OP, + KPD_ERR_CONFIG_MODE_USED, + subscriber_infos[subscriber_id]->return_path); + return RV_OK; + } + } + + /* Set keys in configurable mode */ + kpd_define_new_config(reference_keys, new_keys); + + /* Send success message to suscriber */ + kpd_send_status_message(KPD_SET_CONFIG_MODE_OP, + KPD_PROCESS_OK, + subscriber_infos[subscriber_id]->return_path); + +#endif + + return RV_OK; +} + + +/** + * function: kpd_process_key_pressed_i + */ +void kpd_process_key_pressed_i(T_KPD_PHYSICAL_KEY_ID physical_key_pressed_id) +{ + UINT8 i; + UINT32 loop_counter = 0; + UINT16 counter[KPD_MAX_SUBSCRIBER] = {0}; + T_KPD_PHYSICAL_KEY_ID key_id = physical_key_pressed_id; + + KPD_SEND_TRACE_PARAM("KPD: kpd_process_key_pressed_i ", key_id, RV_TRACE_LEVEL_DEBUG_LOW); + + /* Notify subscribers of the key pressed */ + for (i = 0; i < KPD_MAX_SUBSCRIBER; i++) /* To do : Loop on the real number of subscribers */ + { /* To do : Test on the physical_key_mask (to ensure subscriber is subscribed for this key) */ + if ( (subscriber_infos[i]!=0) && (subscriber_infos[i]->notified_keys.notif_level[key_id] & KPD_FIRST_PRESS_NOTIF) ) + { + kpd_send_key_event_message(key_id, KPD_KEY_PRESSED, + KPD_FIRST_PRESS, subscriber_infos[i]->mode, + subscriber_infos[i]->return_path); + } + } + + /* If key pressed is the PWR key, the message "Released key" is immediately sent */ + if (key_id != KPD_SHORT_PRESS_PWR_KEY) + { + /* Loop infinitely until key is released */ + do + { + rvf_delay(RVF_MS_TO_TICKS(WAIT_TIME_LOOP)); + physical_key_pressed_id = kpd_scan_keypad(); + loop_counter++; + + /* Send message for repeat key */ + for (i = 0; i < KPD_MAX_SUBSCRIBER; i++) + { + if ( (subscriber_infos[i]!=0) && (subscriber_infos[i]->notified_keys.notif_level[key_id] & (KPD_LONG_PRESS_NOTIF|KPD_INFINITE_REPEAT_NOTIF)) ) + { + if ((counter[i] == 0) && (WAIT_TIME_LOOP*loop_counter >= subscriber_infos[i]->notified_keys.long_press_time) ) + { + kpd_send_key_event_message(key_id, KPD_KEY_PRESSED, + KPD_LONG_PRESS, subscriber_infos[i]->mode, + subscriber_infos[i]->return_path); + counter[i] ++; + } + else if (subscriber_infos[i]->notified_keys.notif_level[key_id] & KPD_INFINITE_REPEAT_NOTIF) + { + if (WAIT_TIME_LOOP*loop_counter >= (UINT32)((counter[i]*subscriber_infos[i]->notified_keys.repeat_time + subscriber_infos[i]->notified_keys.long_press_time)) ) + { + kpd_send_key_event_message(key_id, KPD_KEY_PRESSED, + KPD_REPEAT_PRESS, subscriber_infos[i]->mode, + subscriber_infos[i]->return_path); + counter[i] ++; + } + } + } + } + + } while (physical_key_pressed_id != KPD_PKEY_NULL); + } + + /* Notify subscribers of the key released */ + for (i = 0; i < KPD_MAX_SUBSCRIBER; i++) + { + if ( (subscriber_infos[i]!=0) && (subscriber_infos[i]->notified_keys.notif_level[key_id] & KPD_RELEASE_NOTIF) ) + { + kpd_send_key_event_message(key_id, KPD_KEY_RELEASED, + KPD_INSIGNIFICANT_VALUE, subscriber_infos[i]->mode, + subscriber_infos[i]->return_path); + } + } + + /* On board,this function unmask keypad interrupt + On Riviera tool, this function is empty */ + if (key_id != KPD_SHORT_PRESS_PWR_KEY) + { +#if (CHIPSET == 12) + kpd_software_reset(); + kpd_init_ctrl_reg(1, HARDWARE_DECODING, KPD_CLK_DIV32, + KPD_DETECTION_DISABLED, KPD_DETECTION_DISABLED, + KPD_DETECTION_DISABLED, KPD_DETECTION_DISABLED); +#endif + + kpd_acknowledge_key_pressed(); + } +} + + +/** + * function: kpd_process_key_pressed_sn_mode_i + */ +void kpd_process_key_pressed_sn_mode_i(T_KPD_PHYSICAL_KEY_ID physical_key_pressed_id) +{ + T_SUBSCRIBER_ID owner_keypad_id = kpd_get_owner_keypad_id(); + T_KPD_PHYSICAL_KEY_ID key_id = physical_key_pressed_id; + UINT32 loop_counter = 0; + UINT16 counter = 0; + + if ( subscriber_infos[owner_keypad_id]->notified_keys.notif_level[key_id] & KPD_FIRST_PRESS_NOTIF ) + { + /* Notify subscribers of the key pressed */ + kpd_send_key_event_message(key_id, KPD_KEY_PRESSED, + KPD_FIRST_PRESS, subscriber_infos[owner_keypad_id]->mode, + subscriber_infos[owner_keypad_id]->return_path); + } + + /* If key pressed is the PWR key, the message "Released key" is immediately sent */ + if (key_id != KPD_SHORT_PRESS_PWR_KEY) + { + /* Loop infinitely until key is released */ + do + { + rvf_delay(RVF_MS_TO_TICKS(WAIT_TIME_LOOP)); + physical_key_pressed_id = kpd_scan_keypad(); + loop_counter++; + + /* Send message for repeat key */ + if (subscriber_infos[owner_keypad_id]->notified_keys.notif_level[key_id] & (KPD_LONG_PRESS_NOTIF|KPD_INFINITE_REPEAT_NOTIF)) + { + if ((counter == 0) && (WAIT_TIME_LOOP*loop_counter >= subscriber_infos[owner_keypad_id]->notified_keys.long_press_time) ) + { + kpd_send_key_event_message(key_id, KPD_KEY_PRESSED, + KPD_LONG_PRESS, subscriber_infos[owner_keypad_id]->mode, + subscriber_infos[owner_keypad_id]->return_path); + counter ++; + } + else if (subscriber_infos[owner_keypad_id]->notified_keys.notif_level[key_id] & KPD_INFINITE_REPEAT_NOTIF) + { + if (WAIT_TIME_LOOP*loop_counter >= (UINT32)((counter*subscriber_infos[owner_keypad_id]->notified_keys.repeat_time + subscriber_infos[owner_keypad_id]->notified_keys.long_press_time)) ) + { + kpd_send_key_event_message(key_id, KPD_KEY_PRESSED, + KPD_REPEAT_PRESS, subscriber_infos[owner_keypad_id]->mode, + subscriber_infos[owner_keypad_id]->return_path); + counter ++; + } + } + } + + } while (physical_key_pressed_id != KPD_PKEY_NULL); + } + + if ( subscriber_infos[owner_keypad_id]->notified_keys.notif_level[key_id] & KPD_RELEASE_NOTIF ) + { + /* Notify subscribers of the key released */ + kpd_send_key_event_message(key_id, KPD_KEY_RELEASED, + KPD_INSIGNIFICANT_VALUE, subscriber_infos[owner_keypad_id]->mode, + subscriber_infos[owner_keypad_id]->return_path); + } + + /* On board,this function unmask keypad interrupt + On Riviera tool, this function authorize to send new messages to keypad task */ + if (key_id != KPD_SHORT_PRESS_PWR_KEY) + { +#if (CHIPSET == 12) + kpd_software_reset(); + kpd_init_ctrl_reg(1, HARDWARE_DECODING, KPD_CLK_DIV32, + KPD_DETECTION_DISABLED, KPD_DETECTION_DISABLED, + KPD_DETECTION_DISABLED, KPD_DETECTION_DISABLED); +#endif + kpd_acknowledge_key_pressed(); + } +} + +/** + * function: kpd_wait_for_key_release + */ +void kpd_wait_for_key_release(void) +{ + T_KPD_PHYSICAL_KEY_ID key_id;; + + do + { + rvf_delay(RVF_MS_TO_TICKS(WAIT_TIME_LOOP)); + key_id = kpd_scan_keypad(); + + } while (key_id != KPD_PKEY_NULL); + + kpd_acknowledge_key_pressed(); +} + +/*@}*/