1 /**
2  * @file hal_indev.c
3  *
4  * @description Input device HAL interface
5  *
6  */
7 
8 /*********************
9  *      INCLUDES
10  *********************/
11 #include "../lv_misc/lv_debug.h"
12 #include "../lv_hal/lv_hal_indev.h"
13 #include "../lv_core/lv_indev.h"
14 #include "../lv_misc/lv_mem.h"
15 #include "../lv_misc/lv_gc.h"
16 #include "lv_hal_disp.h"
17 
18 #if defined(LV_GC_INCLUDE)
19     #include LV_GC_INCLUDE
20 #endif /* LV_ENABLE_GC */
21 
22 /*********************
23  *      DEFINES
24  *********************/
25 
26 /**********************
27  *      TYPEDEFS
28  **********************/
29 
30 /**********************
31  *  STATIC PROTOTYPES
32  **********************/
33 
34 /**********************
35  *  STATIC VARIABLES
36  **********************/
37 
38 /**********************
39  *      MACROS
40  **********************/
41 
42 /**********************
43  *   GLOBAL FUNCTIONS
44  **********************/
45 
46 /**
47  * Initialize an input device driver with default values.
48  * It is used to surly have known values in the fields ant not memory junk.
49  * After it you can set the fields.
50  * @param driver pointer to driver variable to initialize
51  */
lv_indev_drv_init(lv_indev_drv_t * driver)52 void lv_indev_drv_init(lv_indev_drv_t * driver)
53 {
54     _lv_memset_00(driver, sizeof(lv_indev_drv_t));
55 
56     driver->type                 = LV_INDEV_TYPE_NONE;
57     driver->drag_limit           = LV_INDEV_DEF_DRAG_LIMIT;
58     driver->drag_throw           = LV_INDEV_DEF_DRAG_THROW;
59     driver->long_press_time      = LV_INDEV_DEF_LONG_PRESS_TIME;
60     driver->long_press_rep_time  = LV_INDEV_DEF_LONG_PRESS_REP_TIME;
61     driver->gesture_limit        = LV_INDEV_DEF_GESTURE_LIMIT;
62     driver->gesture_min_velocity = LV_INDEV_DEF_GESTURE_MIN_VELOCITY;
63 }
64 
65 /**
66  * Register an initialized input device driver.
67  * @param driver pointer to an initialized 'lv_indev_drv_t' variable (can be local variable)
68  * @return pointer to the new input device or NULL on error
69  */
lv_indev_drv_register(lv_indev_drv_t * driver)70 lv_indev_t * lv_indev_drv_register(lv_indev_drv_t * driver)
71 {
72 
73     if(driver->disp == NULL) driver->disp = lv_disp_get_default();
74 
75     if(driver->disp == NULL) {
76         LV_LOG_WARN("lv_indev_drv_register: no display registered hence can't attach the indev to "
77                     "a display");
78         return NULL;
79     }
80 
81     lv_indev_t * indev = _lv_ll_ins_head(&LV_GC_ROOT(_lv_indev_ll));
82     if(!indev) {
83         LV_ASSERT_MEM(indev);
84         return NULL;
85     }
86 
87     _lv_memset_00(indev, sizeof(lv_indev_t));
88     _lv_memcpy(&indev->driver, driver, sizeof(lv_indev_drv_t));
89 
90     indev->proc.reset_query = 1;
91     indev->cursor           = NULL;
92     indev->group            = NULL;
93     indev->btn_points       = NULL;
94 
95     indev->driver.read_task = lv_task_create(_lv_indev_read_task, LV_INDEV_DEF_READ_PERIOD, LV_TASK_PRIO_HIGH, indev);
96 
97     return indev;
98 }
99 
100 /**
101  * Update the driver in run time.
102  * @param indev pointer to a input device. (return value of `lv_indev_drv_register`)
103  * @param new_drv pointer to the new driver
104  */
lv_indev_drv_update(lv_indev_t * indev,lv_indev_drv_t * new_drv)105 void lv_indev_drv_update(lv_indev_t * indev, lv_indev_drv_t * new_drv)
106 {
107     memcpy(&indev->driver, new_drv, sizeof(lv_indev_drv_t));
108 }
109 
110 /**
111  * Get the next input device.
112  * @param indev pointer to the current input device. NULL to initialize.
113  * @return the next input devise or NULL if no more. Give the first input device when the parameter
114  * is NULL
115  */
lv_indev_get_next(lv_indev_t * indev)116 lv_indev_t * lv_indev_get_next(lv_indev_t * indev)
117 {
118     if(indev == NULL)
119         return _lv_ll_get_head(&LV_GC_ROOT(_lv_indev_ll));
120     else
121         return _lv_ll_get_next(&LV_GC_ROOT(_lv_indev_ll), indev);
122 }
123 
124 /**
125  * Read data from an input device.
126  * @param indev pointer to an input device
127  * @param data input device will write its data here
128  * @return false: no more data; true: there more data to read (buffered)
129  */
_lv_indev_read(lv_indev_t * indev,lv_indev_data_t * data)130 bool _lv_indev_read(lv_indev_t * indev, lv_indev_data_t * data)
131 {
132     bool cont = false;
133 
134     _lv_memset_00(data, sizeof(lv_indev_data_t));
135 
136     /* For touchpad sometimes users don't the last pressed coordinate on release.
137      * So be sure a coordinates are initialized to the last point */
138     if(indev->driver.type == LV_INDEV_TYPE_POINTER) {
139         data->point.x = indev->proc.types.pointer.act_point.x;
140         data->point.y = indev->proc.types.pointer.act_point.y;
141     }
142     /*Similarly set at least the last key in case of the  the user doesn't set it  on release*/
143     else if(indev->driver.type == LV_INDEV_TYPE_KEYPAD) {
144         data->key = indev->proc.types.keypad.last_key;
145     }
146     /*For compatibility assume that used button was enter (encoder push) */
147     else if(indev->driver.type == LV_INDEV_TYPE_ENCODER) {
148         data->key = LV_KEY_ENTER;
149         data->enc_diff = 0;
150     }
151 
152     if(indev->driver.read_cb) {
153         LV_LOG_TRACE("idnev read started");
154         cont = indev->driver.read_cb(&indev->driver, data);
155         LV_LOG_TRACE("idnev read finished");
156     }
157     else {
158         LV_LOG_WARN("indev function registered");
159     }
160 
161     return cont;
162 }
163 
164 /**********************
165  *   STATIC FUNCTIONS
166  **********************/
167