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 * 22 * Filename: btif_sm.c 23 * 24 * Description: Generic BTIF state machine API 25 * 26 *****************************************************************************/ 27 28 #define LOG_TAG "bt_btif" 29 30 #include <hardware/bluetooth.h> 31 32 #include "osi/include/allocator.h" 33 #include "btif_common.h" 34 #include "btif_sm.h" 35 #include "gki.h" 36 37 /***************************************************************************** 38 ** Constants & Macros 39 ******************************************************************************/ 40 41 42 /***************************************************************************** 43 ** Local type definitions 44 ******************************************************************************/ 45 typedef struct { 46 btif_sm_state_t state; 47 btif_sm_handler_t *p_handlers; 48 } btif_sm_cb_t; 49 50 /***************************************************************************** 51 ** Static variables 52 ******************************************************************************/ 53 54 /***************************************************************************** 55 ** Static functions 56 ******************************************************************************/ 57 58 /***************************************************************************** 59 ** Externs 60 ******************************************************************************/ 61 62 /***************************************************************************** 63 ** Functions 64 ******************************************************************************/ 65 66 /***************************************************************************** 67 ** 68 ** Function btif_sm_init 69 ** 70 ** Description Initializes the state machine with the state handlers 71 ** The caller should ensure that the table and the corresponding 72 ** states match. The location that 'p_handlers' points to shall 73 ** be available until the btif_sm_shutdown API is invoked. 74 ** 75 ** Returns Returns a pointer to the initialized state machine handle. 76 ** 77 ******************************************************************************/ 78 79 btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers, btif_sm_state_t initial_state) 80 { 81 btif_sm_cb_t *p_cb; 82 83 if (p_handlers == NULL) 84 { 85 BTIF_TRACE_ERROR("%s : p_handlers is NULL", __FUNCTION__); 86 return NULL; 87 } 88 89 p_cb = (btif_sm_cb_t *)osi_malloc(sizeof(btif_sm_cb_t)); 90 p_cb->state = initial_state; 91 p_cb->p_handlers = (btif_sm_handler_t*)p_handlers; 92 93 /* Send BTIF_SM_ENTER_EVT to the initial state */ 94 p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL); 95 96 return (btif_sm_handle_t)p_cb; 97 } 98 99 /***************************************************************************** 100 ** 101 ** Function btif_sm_shutdown 102 ** 103 ** Description Tears down the state machine 104 ** 105 ** Returns None 106 ** 107 ******************************************************************************/ 108 void btif_sm_shutdown(btif_sm_handle_t handle) 109 { 110 btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; 111 112 if (p_cb == NULL) 113 { 114 BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); 115 return; 116 } 117 osi_free(p_cb); 118 } 119 120 /***************************************************************************** 121 ** 122 ** Function btif_sm_get_state 123 ** 124 ** Description Fetches the current state of the state machine 125 ** 126 ** Returns Current state 127 ** 128 ******************************************************************************/ 129 btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle) 130 { 131 btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; 132 133 if (p_cb == NULL) 134 { 135 BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); 136 return 0; 137 } 138 139 return p_cb->state; 140 } 141 142 /***************************************************************************** 143 ** 144 ** Function btif_sm_dispatch 145 ** 146 ** Description Dispatches the 'event' along with 'data' to the current state handler 147 ** 148 ** Returns BT_STATUS_SUCCESS on success 149 ** BT_STATUS_UNHANDLED if event was not processed 150 ** BT_STATUS_FAIL otherwise 151 ** 152 ******************************************************************************/ 153 bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event, 154 void *data) 155 { 156 bt_status_t status = BT_STATUS_SUCCESS; 157 158 btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; 159 160 if (p_cb == NULL) 161 { 162 BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); 163 return BT_STATUS_FAIL; 164 } 165 166 if (p_cb->p_handlers[p_cb->state](event, data) == FALSE) 167 return BT_STATUS_UNHANDLED; 168 169 return status; 170 } 171 172 /***************************************************************************** 173 ** 174 ** Function btif_sm_change_state 175 ** 176 ** Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT' 177 ** shall be invoked before exiting the current state. The 178 ** 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new state 179 ** 180 ** Returns BT_STATUS_SUCCESS on success 181 ** BT_STATUS_UNHANDLED if event was not processed 182 ** BT_STATUS_FAIL otherwise 183 ** 184 ******************************************************************************/ 185 bt_status_t btif_sm_change_state(btif_sm_handle_t handle, btif_sm_state_t state) 186 { 187 bt_status_t status = BT_STATUS_SUCCESS; 188 btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; 189 190 if (p_cb == NULL) 191 { 192 BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); 193 return BT_STATUS_FAIL; 194 } 195 196 /* Send exit event to the current state */ 197 if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL) == FALSE) 198 status = BT_STATUS_UNHANDLED; 199 200 /* Change to the new state */ 201 p_cb->state = state; 202 203 /* Send enter event to the new state */ 204 if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL) == FALSE) 205 status = BT_STATUS_UNHANDLED; 206 207 return status; 208 } 209