1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15
16 /*****************************************************************************
17 *
18 * Filename: btc_sm.c
19 *
20 * Description: Generic BTC state machine API
21 *
22 *****************************************************************************/
23 #include "common/bt_target.h"
24 #include "common/bt_defs.h"
25 #include "osi/allocator.h"
26 #include "btc/btc_common.h"
27 #include "btc/btc_sm.h"
28
29 #if BTC_SM_INCLUDED
30 /*****************************************************************************
31 ** Constants & Macros
32 ******************************************************************************/
33 /*****************************************************************************
34 ** Local type definitions
35 ******************************************************************************/
36 typedef struct {
37 btc_sm_state_t state;
38 btc_sm_handler_t *p_handlers;
39 } btc_sm_cb_t;
40
41 /*****************************************************************************
42 ** Static variables
43 ******************************************************************************/
44
45 /*****************************************************************************
46 ** Static functions
47 ******************************************************************************/
48
49 /*****************************************************************************
50 ** Externs
51 ******************************************************************************/
52
53 /*****************************************************************************
54 ** Functions
55 ******************************************************************************/
56
57 /*****************************************************************************
58 **
59 ** Function btc_sm_init
60 **
61 ** Description Initializes the state machine with the state handlers
62 ** The caller should ensure that the table and the corresponding
63 ** states match. The location that 'p_handlers' points to shall
64 ** be available until the btc_sm_shutdown API is invoked.
65 **
66 ** Returns Returns a pointer to the initialized state machine handle.
67 **
68 ******************************************************************************/
69
btc_sm_init(const btc_sm_handler_t * p_handlers,btc_sm_state_t initial_state)70 btc_sm_handle_t btc_sm_init(const btc_sm_handler_t *p_handlers, btc_sm_state_t initial_state)
71 {
72 btc_sm_cb_t *p_cb;
73
74 if (p_handlers == NULL) {
75 BTC_TRACE_ERROR("%s : p_handlers is NULL", __FUNCTION__);
76 return NULL;
77 }
78
79 p_cb = (btc_sm_cb_t *)osi_malloc(sizeof(btc_sm_cb_t));
80 p_cb->state = initial_state;
81 p_cb->p_handlers = (btc_sm_handler_t *)p_handlers;
82
83 /* Send BTC_SM_ENTER_EVT to the initial state */
84 p_cb->p_handlers[initial_state](BTC_SM_ENTER_EVT, NULL);
85
86 return (btc_sm_handle_t)p_cb;
87 }
88
89 /*****************************************************************************
90 **
91 ** Function btc_sm_shutdown
92 **
93 ** Description Tears down the state machine
94 **
95 ** Returns None
96 **
97 ******************************************************************************/
btc_sm_shutdown(btc_sm_handle_t handle)98 void btc_sm_shutdown(btc_sm_handle_t handle)
99 {
100 btc_sm_cb_t *p_cb = (btc_sm_cb_t *)handle;
101
102 if (p_cb == NULL) {
103 BTC_TRACE_ERROR("%s : Invalid handle", __FUNCTION__);
104 return;
105 }
106 osi_free(p_cb);
107 }
108
109 /*****************************************************************************
110 **
111 ** Function btc_sm_get_state
112 **
113 ** Description Fetches the current state of the state machine
114 **
115 ** Returns Current state
116 **
117 ******************************************************************************/
btc_sm_get_state(btc_sm_handle_t handle)118 btc_sm_state_t btc_sm_get_state(btc_sm_handle_t handle)
119 {
120 btc_sm_cb_t *p_cb = (btc_sm_cb_t *)handle;
121
122 if (p_cb == NULL) {
123 BTC_TRACE_ERROR("%s : Invalid handle", __FUNCTION__);
124 return 0;
125 }
126
127 return p_cb->state;
128 }
129
130 /*****************************************************************************
131 **
132 ** Function btc_sm_dispatch
133 **
134 ** Description Dispatches the 'event' along with 'data' to the current state handler
135 **
136 ** Returns BT_STATUS_SUCCESS on success
137 ** BT_STATUS_UNHANDLED if event was not processed
138 ** BT_STATUS_FAIL otherwise
139 **
140 ******************************************************************************/
btc_sm_dispatch(btc_sm_handle_t handle,btc_sm_event_t event,void * data)141 bt_status_t btc_sm_dispatch(btc_sm_handle_t handle, btc_sm_event_t event,
142 void *data)
143 {
144 bt_status_t status = BT_STATUS_SUCCESS;
145
146 btc_sm_cb_t *p_cb = (btc_sm_cb_t *)handle;
147
148 if (p_cb == NULL) {
149 BTC_TRACE_ERROR("%s : Invalid handle", __FUNCTION__);
150 return BT_STATUS_FAIL;
151 }
152
153 if (p_cb->p_handlers[p_cb->state](event, data) == FALSE) {
154 return BT_STATUS_UNHANDLED;
155 }
156
157 return status;
158 }
159
160 /*****************************************************************************
161 **
162 ** Function btc_sm_change_state
163 **
164 ** Description Make a transition to the new 'state'. The 'BTC_SM_EXIT_EVT'
165 ** shall be invoked before exiting the current state. The
166 ** 'BTC_SM_ENTER_EVT' shall be invoked before entering the new state
167 **
168 ** Returns BT_STATUS_SUCCESS on success
169 ** BT_STATUS_UNHANDLED if event was not processed
170 ** BT_STATUS_FAIL otherwise
171 **
172 ******************************************************************************/
btc_sm_change_state(btc_sm_handle_t handle,btc_sm_state_t state)173 bt_status_t btc_sm_change_state(btc_sm_handle_t handle, btc_sm_state_t state)
174 {
175 bt_status_t status = BT_STATUS_SUCCESS;
176 btc_sm_cb_t *p_cb = (btc_sm_cb_t *)handle;
177
178 if (p_cb == NULL) {
179 BTC_TRACE_ERROR("%s : Invalid handle", __FUNCTION__);
180 return BT_STATUS_FAIL;
181 }
182
183 /* Send exit event to the current state */
184 if (p_cb->p_handlers[p_cb->state](BTC_SM_EXIT_EVT, NULL) == FALSE) {
185 status = BT_STATUS_UNHANDLED;
186 }
187
188 /* Change to the new state */
189 p_cb->state = state;
190
191 /* Send enter event to the new state */
192 if (p_cb->p_handlers[p_cb->state](BTC_SM_ENTER_EVT, NULL) == FALSE) {
193 status = BT_STATUS_UNHANDLED;
194 }
195
196 return status;
197 }
198
199 #endif /* #if BTC_SM_INCLUDED */
200