Home | History | Annotate | Download | only in src
      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