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