/** * Copyright (c) 2010-2012 Broadcom. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The names of the above-listed copyright holders may not be used * to endorse or promote products derived from this software without * specific prior written permission. * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2, as published by the Free * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "vchiq_connected.h" #include "vchiq_core.h" #include "vchiq_killable.h" #include #include #define MAX_CALLBACKS 10 static int g_connected; static int g_num_deferred_callbacks; static VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS]; static int g_once_init; static struct mutex g_connected_mutex; /**************************************************************************** * * Function to initialize our lock. * ***************************************************************************/ static void connected_init(void) { if (!g_once_init) { mutex_init(&g_connected_mutex); g_once_init = 1; } } /**************************************************************************** * * This function is used to defer initialization until the vchiq stack is * initialized. If the stack is already initialized, then the callback will * be made immediately, otherwise it will be deferred until * vchiq_call_connected_callbacks is called. * ***************************************************************************/ void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback) { connected_init(); if (mutex_lock_killable(&g_connected_mutex) != 0) return; if (g_connected) /* We're already connected. Call the callback immediately. */ callback(); else { if (g_num_deferred_callbacks >= MAX_CALLBACKS) vchiq_log_error(vchiq_core_log_level, "There already %d callback registered - " "please increase MAX_CALLBACKS", g_num_deferred_callbacks); else { g_deferred_callback[g_num_deferred_callbacks] = callback; g_num_deferred_callbacks++; } } mutex_unlock(&g_connected_mutex); } /**************************************************************************** * * This function is called by the vchiq stack once it has been connected to * the videocore and clients can start to use the stack. * ***************************************************************************/ void vchiq_call_connected_callbacks(void) { int i; connected_init(); if (mutex_lock_killable(&g_connected_mutex) != 0) return; for (i = 0; i < g_num_deferred_callbacks; i++) g_deferred_callback[i](); g_num_deferred_callbacks = 0; g_connected = 1; mutex_unlock(&g_connected_mutex); } EXPORT_SYMBOL(vchiq_add_connected_callback);