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 "btif_common.h" 32 #include "bt_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, btif_sm_state_t initial_state) 61 { 62 if (p_handlers == NULL) { 63 BTIF_TRACE_ERROR("%s : p_handlers is NULL", __FUNCTION__); 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 { 88 btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; 89 90 if (p_cb == NULL) 91 { 92 BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); 93 return; 94 } 95 osi_free(p_cb); 96 } 97 98 /***************************************************************************** 99 ** 100 ** Function btif_sm_get_state 101 ** 102 ** Description Fetches the current state of the state machine 103 ** 104 ** Returns Current state 105 ** 106 ******************************************************************************/ 107 btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle) 108 { 109 btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; 110 111 if (p_cb == NULL) 112 { 113 BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); 114 return 0; 115 } 116 117 return p_cb->state; 118 } 119 120 /***************************************************************************** 121 ** 122 ** Function btif_sm_dispatch 123 ** 124 ** Description Dispatches the 'event' along with 'data' to the current state handler 125 ** 126 ** Returns BT_STATUS_SUCCESS on success 127 ** BT_STATUS_UNHANDLED if event was not processed 128 ** BT_STATUS_FAIL otherwise 129 ** 130 ******************************************************************************/ 131 bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event, 132 void *data) 133 { 134 bt_status_t status = BT_STATUS_SUCCESS; 135 136 btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; 137 138 if (p_cb == NULL) 139 { 140 BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); 141 return BT_STATUS_FAIL; 142 } 143 144 if (p_cb->p_handlers[p_cb->state](event, data) == FALSE) 145 return BT_STATUS_UNHANDLED; 146 147 return status; 148 } 149 150 /***************************************************************************** 151 ** 152 ** Function btif_sm_change_state 153 ** 154 ** Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT' 155 ** shall be invoked before exiting the current state. The 156 ** 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new state 157 ** 158 ** Returns BT_STATUS_SUCCESS on success 159 ** BT_STATUS_UNHANDLED if event was not processed 160 ** BT_STATUS_FAIL otherwise 161 ** 162 ******************************************************************************/ 163 bt_status_t btif_sm_change_state(btif_sm_handle_t handle, btif_sm_state_t state) 164 { 165 bt_status_t status = BT_STATUS_SUCCESS; 166 btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; 167 168 if (p_cb == NULL) 169 { 170 BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); 171 return BT_STATUS_FAIL; 172 } 173 174 /* Send exit event to the current state */ 175 if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL) == FALSE) 176 status = BT_STATUS_UNHANDLED; 177 178 /* Change to the new state */ 179 p_cb->state = state; 180 181 /* Send enter event to the new state */ 182 if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL) == FALSE) 183 status = BT_STATUS_UNHANDLED; 184 185 return status; 186 } 187