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 #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 
     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_ERROR1("%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 ******************************************************************************/
    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_ERROR1("%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 ******************************************************************************/
    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_ERROR1("%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 ******************************************************************************/
    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_ERROR1("%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 ******************************************************************************/
    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_ERROR1("%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