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