1 /****************************************************************************** 2 * 3 * Copyright (C) 2009-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /***************************************************************************** 20 * 21 * Filename: btif_sm.c 22 * 23 * Description: Generic BTIF state machine API 24 * 25 *****************************************************************************/ 26 27 #define LOG_TAG "bt_btif" 28 29 #include "btif_sm.h" 30 31 #include "bt_common.h" 32 #include "btif_common.h" 33 #include "osi/include/allocator.h" 34 35 /***************************************************************************** 36 * Local type definitions 37 *****************************************************************************/ 38 typedef struct { 39 btif_sm_state_t state; 40 btif_sm_handler_t* p_handlers; 41 } btif_sm_cb_t; 42 43 /***************************************************************************** 44 * Functions 45 *****************************************************************************/ 46 47 /***************************************************************************** 48 * 49 * Function btif_sm_init 50 * 51 * Description Initializes the state machine with the state handlers 52 * The caller should ensure that the table and the corresponding 53 * states match. The location that 'p_handlers' points to shall 54 * be available until the btif_sm_shutdown API is invoked. 55 * 56 * Returns Returns a pointer to the initialized state machine handle. 57 * 58 *****************************************************************************/ 59 60 btif_sm_handle_t btif_sm_init(const btif_sm_handler_t* p_handlers, 61 btif_sm_state_t initial_state) { 62 if (p_handlers == NULL) { 63 BTIF_TRACE_ERROR("%s : p_handlers is NULL", __func__); 64 return NULL; 65 } 66 67 btif_sm_cb_t* p_cb = (btif_sm_cb_t*)osi_malloc(sizeof(btif_sm_cb_t)); 68 p_cb->state = initial_state; 69 p_cb->p_handlers = (btif_sm_handler_t*)p_handlers; 70 71 /* Send BTIF_SM_ENTER_EVT to the initial state */ 72 p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL); 73 74 return (btif_sm_handle_t)p_cb; 75 } 76 77 /***************************************************************************** 78 * 79 * Function btif_sm_shutdown 80 * 81 * Description Tears down the state machine 82 * 83 * Returns None 84 * 85 *****************************************************************************/ 86 void btif_sm_shutdown(btif_sm_handle_t handle) { 87 btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle; 88 89 if (p_cb == NULL) { 90 BTIF_TRACE_ERROR("%s : Invalid handle", __func__); 91 return; 92 } 93 osi_free(p_cb); 94 } 95 96 /***************************************************************************** 97 * 98 * Function btif_sm_get_state 99 * 100 * Description Fetches the current state of the state machine 101 * 102 * Returns Current state 103 * 104 *****************************************************************************/ 105 btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle) { 106 btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle; 107 108 if (p_cb == NULL) { 109 BTIF_TRACE_ERROR("%s : Invalid handle", __func__); 110 return 0; 111 } 112 113 return p_cb->state; 114 } 115 116 /***************************************************************************** 117 * 118 * Function btif_sm_dispatch 119 * 120 * Description Dispatches the 'event' along with 'data' to the current state 121 * handler 122 * 123 * Returns BT_STATUS_SUCCESS on success 124 * BT_STATUS_UNHANDLED if event was not processed 125 * BT_STATUS_FAIL otherwise 126 * 127 *****************************************************************************/ 128 bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event, 129 void* data) { 130 bt_status_t status = BT_STATUS_SUCCESS; 131 132 btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle; 133 134 if (p_cb == NULL) { 135 BTIF_TRACE_ERROR("%s : Invalid handle", __func__); 136 return BT_STATUS_FAIL; 137 } 138 139 if (p_cb->p_handlers[p_cb->state](event, data) == false) 140 return BT_STATUS_UNHANDLED; 141 142 return status; 143 } 144 145 /***************************************************************************** 146 * 147 * Function btif_sm_change_state 148 * 149 * Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT' 150 * shall be invoked before exiting the current state. The 151 * 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new 152 * state 153 * 154 * Returns BT_STATUS_SUCCESS on success 155 * BT_STATUS_UNHANDLED if event was not processed 156 * BT_STATUS_FAIL otherwise 157 * 158 *****************************************************************************/ 159 bt_status_t btif_sm_change_state(btif_sm_handle_t handle, 160 btif_sm_state_t state) { 161 bt_status_t status = BT_STATUS_SUCCESS; 162 btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle; 163 164 if (p_cb == NULL) { 165 BTIF_TRACE_ERROR("%s : Invalid handle", __func__); 166 return BT_STATUS_FAIL; 167 } 168 169 /* Send exit event to the current state */ 170 if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL) == false) 171 status = BT_STATUS_UNHANDLED; 172 173 /* Change to the new state */ 174 p_cb->state = state; 175 176 /* Send enter event to the new state */ 177 if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL) == false) 178 status = BT_STATUS_UNHANDLED; 179 180 return status; 181 } 182