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