/** * @file lv_hal_indev.c * * @description Input device HAL interface * */ /********************* * INCLUDES *********************/ #include "../misc/lv_assert.h" #include "../hal/lv_hal_indev.h" #include "../core/lv_indev.h" #include "../misc/lv_mem.h" #include "../misc/lv_gc.h" #include "lv_hal_disp.h" /********************* * DEFINES *********************/ /********************** * TYPEDEFS **********************/ /********************** * GLOBAL PROTOTYPES **********************/ /********************** * STATIC PROTOTYPES **********************/ /********************** * STATIC VARIABLES **********************/ /********************** * MACROS **********************/ #if LV_LOG_TRACE_INDEV #define INDEV_TRACE(...) LV_LOG_TRACE(__VA_ARGS__) #else #define INDEV_TRACE(...) #endif /********************** * GLOBAL FUNCTIONS **********************/ /** * Initialize an input device driver with default values. * It is used to surly have known values in the fields ant not memory junk. * After it you can set the fields. * @param driver pointer to driver variable to initialize */ void lv_indev_drv_init(lv_indev_drv_t * driver) { lv_memset_00(driver, sizeof(lv_indev_drv_t)); driver->type = LV_INDEV_TYPE_NONE; driver->scroll_limit = LV_INDEV_DEF_SCROLL_LIMIT; driver->scroll_throw = LV_INDEV_DEF_SCROLL_THROW; driver->long_press_time = LV_INDEV_DEF_LONG_PRESS_TIME; driver->long_press_repeat_time = LV_INDEV_DEF_LONG_PRESS_REP_TIME; driver->gesture_limit = LV_INDEV_DEF_GESTURE_LIMIT; driver->gesture_min_velocity = LV_INDEV_DEF_GESTURE_MIN_VELOCITY; } /** * Register an initialized input device driver. * @param driver pointer to an initialized 'lv_indev_drv_t' variable. * Only pointer is saved, so the driver should be static or dynamically allocated. * @return pointer to the new input device or NULL on error */ lv_indev_t * lv_indev_drv_register(lv_indev_drv_t * driver) { if(driver->disp == NULL) driver->disp = lv_disp_get_default(); if(driver->disp == NULL) { LV_LOG_WARN("lv_indev_drv_register: no display registered hence can't attach the indev to " "a display"); return NULL; } lv_indev_t * indev = _lv_ll_ins_head(&LV_GC_ROOT(_lv_indev_ll)); if(!indev) { LV_ASSERT_MALLOC(indev); return NULL; } lv_memset_00(indev, sizeof(lv_indev_t)); indev->driver = driver; indev->proc.reset_query = 1; indev->driver->read_timer = lv_timer_create(lv_indev_read_timer_cb, LV_INDEV_DEF_READ_PERIOD, indev); return indev; } /** * Update the driver in run time. * @param indev pointer to a input device. (return value of `lv_indev_drv_register`) * @param new_drv pointer to the new driver */ void lv_indev_drv_update(lv_indev_t * indev, lv_indev_drv_t * new_drv) { LV_ASSERT_NULL(indev); LV_ASSERT_NULL(indev->driver); LV_ASSERT_NULL(indev->driver->read_timer); lv_timer_del(indev->driver->read_timer); LV_ASSERT_NULL(new_drv); if(new_drv->disp == NULL) { new_drv->disp = lv_disp_get_default(); } if(new_drv->disp == NULL) { LV_LOG_WARN("lv_indev_drv_register: no display registered hence can't attach the indev to " "a display"); indev->proc.disabled = true; return; } indev->driver = new_drv; indev->driver->read_timer = lv_timer_create(lv_indev_read_timer_cb, LV_INDEV_DEF_READ_PERIOD, indev); indev->proc.reset_query = 1; } /** * Remove the provided input device. Make sure not to use the provided input device afterwards anymore. * @param indev pointer to delete */ void lv_indev_delete(lv_indev_t * indev) { LV_ASSERT_NULL(indev); LV_ASSERT_NULL(indev->driver); LV_ASSERT_NULL(indev->driver->read_timer); /*Clean up the read timer first*/ lv_timer_del(indev->driver->read_timer); /*Remove the input device from the list*/ _lv_ll_remove(&LV_GC_ROOT(_lv_indev_ll), indev); /*Free the memory of the input device*/ lv_mem_free(indev); } /** * Get the next input device. * @param indev pointer to the current input device. NULL to initialize. * @return the next input devise or NULL if no more. Give the first input device when the parameter * is NULL */ lv_indev_t * lv_indev_get_next(lv_indev_t * indev) { if(indev == NULL) return _lv_ll_get_head(&LV_GC_ROOT(_lv_indev_ll)); else return _lv_ll_get_next(&LV_GC_ROOT(_lv_indev_ll), indev); } /** * Read data from an input device. * @param indev pointer to an input device * @param data input device will write its data here */ void _lv_indev_read(lv_indev_t * indev, lv_indev_data_t * data) { lv_memset_00(data, sizeof(lv_indev_data_t)); /* For touchpad sometimes users don't set the last pressed coordinate on release. * So be sure a coordinates are initialized to the last point */ if(indev->driver->type == LV_INDEV_TYPE_POINTER) { data->point.x = indev->proc.types.pointer.last_raw_point.x; data->point.y = indev->proc.types.pointer.last_raw_point.y; } /*Similarly set at least the last key in case of the user doesn't set it on release*/ else if(indev->driver->type == LV_INDEV_TYPE_KEYPAD) { data->key = indev->proc.types.keypad.last_key; } /*For compatibility assume that used button was enter (encoder push)*/ else if(indev->driver->type == LV_INDEV_TYPE_ENCODER) { data->key = LV_KEY_ENTER; } if(indev->driver->read_cb) { INDEV_TRACE("calling indev_read_cb"); indev->driver->read_cb(indev->driver, data); } else { LV_LOG_WARN("indev_read_cb is not registered"); } } /********************** * STATIC FUNCTIONS **********************/