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
btif_sm_init(const btif_sm_handler_t * p_handlers,btif_sm_state_t initial_state)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 ******************************************************************************/
btif_sm_shutdown(btif_sm_handle_t handle)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 ******************************************************************************/
btif_sm_get_state(btif_sm_handle_t handle)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 ******************************************************************************/
btif_sm_dispatch(btif_sm_handle_t handle,btif_sm_event_t event,void * data)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 ******************************************************************************/
btif_sm_change_state(btif_sm_handle_t handle,btif_sm_state_t state)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