blob: c1bef06fffdb4c02e6761859e1c72ec055942e64 [file] [log] [blame]
// Copyright (c) 2019 The Fuchsia Authors
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
// fee is hereby granted, provided that the above copyright notice and this permission notice
// appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
#include "src/connectivity/wlan/drivers/third_party/broadcom/brcmfmac/timer.h"
#include <lib/async/time.h>
#include <zircon/listnode.h>
#include <zircon/types.h>
static void brcmf_timer_handler(async_dispatcher_t* dispatcher, async_task_t* task,
zx_status_t status) {
if (status != ZX_OK) {
return;
}
brcmf_timer_info_t* timer = containerof(task, brcmf_timer_info_t, task);
timer->callback_function(timer->data);
timer->lock.lock();
timer->scheduled = false;
sync_completion_signal(&timer->finished);
timer->lock.unlock();
}
void brcmf_timer_init(brcmf_timer_info_t* timer, async_dispatcher_t* dispatcher,
brcmf_timer_callback_t* callback, void* data) {
memset(&timer->task.state, 0, sizeof(timer->task.state));
timer->task.handler = brcmf_timer_handler;
timer->dispatcher = dispatcher;
timer->data = data;
timer->callback_function = callback;
timer->finished = {};
timer->scheduled = false;
}
void brcmf_timer_set(brcmf_timer_info_t* timer, zx_duration_t delay) {
timer->lock.lock();
async_cancel_task(timer->dispatcher, &timer->task); // Make sure it's not scheduled
timer->task.deadline = delay + async_now(timer->dispatcher);
timer->scheduled = true;
sync_completion_reset(&timer->finished);
async_post_task(timer->dispatcher, &timer->task);
timer->lock.unlock();
}
void brcmf_timer_stop(brcmf_timer_info_t* timer) {
timer->lock.lock();
if (!timer->scheduled) {
timer->lock.unlock();
return;
}
zx_status_t result = async_cancel_task(timer->dispatcher, &timer->task);
timer->lock.unlock();
if (result != ZX_OK) {
sync_completion_wait(&timer->finished, ZX_TIME_INFINITE);
}
}