/**************************************************************************** * drivers/input/button_lower.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #if CONFIG_BUTTONS_LOWER /**************************************************************************** * Private Function Prototypes ****************************************************************************/ static btn_buttonset_t btn_supported(FAR const struct btn_lowerhalf_s *lower); static btn_buttonset_t btn_buttons(FAR const struct btn_lowerhalf_s *lower); static void btn_enable(FAR const struct btn_lowerhalf_s *lower, btn_buttonset_t press, btn_buttonset_t release, btn_handler_t handler, FAR void *arg); static void btn_disable(void); static int btn_interrupt(int irq, FAR void *context, FAR void *arg); /**************************************************************************** * Private Data ****************************************************************************/ static uint32_t g_btnnum; /* This is the button button lower half driver interface */ static const struct btn_lowerhalf_s g_btnlower = { .bl_supported = btn_supported, .bl_buttons = btn_buttons, .bl_enable = btn_enable, }; /* Current interrupt handler and argument */ static btn_handler_t g_btnhandler; static FAR void *g_btnarg; /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: btn_supported * * Description: * Return the set of buttons supported * ****************************************************************************/ static btn_buttonset_t btn_supported(FAR const struct btn_lowerhalf_s *lower) { iinfo("NUM_BUTTONS: %02" PRIx32 "\n", g_btnnum); return (btn_buttonset_t)((1 << g_btnnum) - 1); } /**************************************************************************** * Name: btn_buttons * * Description: * Return the current state of button data * ****************************************************************************/ static btn_buttonset_t btn_buttons(FAR const struct btn_lowerhalf_s *lower) { return board_buttons(); } /**************************************************************************** * Name: btn_enable * * Description: * Enable interrupts on the selected set of buttons. And empty set or * a NULL handler will disable all interrupts. * ****************************************************************************/ static void btn_enable(FAR const struct btn_lowerhalf_s *lower, btn_buttonset_t press, btn_buttonset_t release, btn_handler_t handler, FAR void *arg) { btn_buttonset_t mask; btn_buttonset_t either = press | release; irqstate_t flags; uint32_t id; /* Start with all interrupts disabled */ flags = enter_critical_section(); btn_disable(); iinfo("press: %02" PRIx32 " release: %02" PRIx32 " handler: %p arg: %p\n", press, release, handler, arg); /* If no events are indicated or if no handler is provided, then this * must really be a request to disable interrupts. */ if (either && handler) { /* Save the new the handler and argument */ g_btnhandler = handler; g_btnarg = arg; /* Attach and enable each button interrupt */ for (id = 0; id < g_btnnum; id++) { mask = (1 << id); if ((either & mask) != 0) { board_button_irq(id, btn_interrupt, NULL); } } } leave_critical_section(flags); } /**************************************************************************** * Name: btn_disable * * Description: * Disable all button interrupts * ****************************************************************************/ static void btn_disable(void) { irqstate_t flags; uint32_t id; /* Disable each button interrupt */ flags = enter_critical_section(); for (id = 0; id < g_btnnum; id++) { board_button_irq(id, NULL, NULL); } /* Nullify the handler and argument */ g_btnhandler = NULL; g_btnarg = NULL; leave_critical_section(flags); } /**************************************************************************** * Name: btn_interrupt * * Description: * Discrete button interrupt handler (all buttons) * ****************************************************************************/ static int btn_interrupt(int irq, FAR void *context, FAR void *arg) { DEBUGASSERT(g_btnhandler); if (g_btnhandler) { g_btnhandler(&g_btnlower, g_btnarg); } return OK; } /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: btn_lower_initialize * * Description: * Initialize the generic button lower half driver, bind it and register * it with the upper half button driver as devname. * ****************************************************************************/ int btn_lower_initialize(FAR const char *devname) { g_btnnum = board_button_initialize(); return btn_register(devname, &g_btnlower); } #endif /* CONFIG_BUTTONS_LOWER */