fix dependency check logic cause config always disabled
[lunaix-os.git] / lunaix-os / kernel / device / input.c
1 #include <lunaix/clock.h>
2 #include <lunaix/input.h>
3 #include <lunaix/mm/pagetable.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/spike.h>
6 #include <lunaix/status.h>
7
8 #include <klibc/string.h>
9
10 static DEFINE_LLIST(listener_chain);
11
12 static struct device_cat* input_devcat = NULL;
13
14 void
15 input_init()
16 {
17     input_devcat = device_addcat(NULL, "input");
18 }
19
20 void
21 input_fire_event(struct input_device* idev, struct input_evt_pkt* pkt)
22 {
23     pkt->timestamp = clock_systime();
24     idev->current_pkt = *pkt;
25
26     struct input_evt_chain *pos, *n;
27     llist_for_each(pos, n, &listener_chain, chain)
28     {
29         if (pos->evt_cb(idev) == INPUT_EVT_CATCH) {
30             break;
31         }
32     }
33
34     // wake up all pending readers
35     pwake_all(&idev->readers);
36 }
37
38 void
39 input_add_listener(input_evt_cb listener)
40 {
41     assert(listener);
42
43     struct input_evt_chain* chain = vzalloc(sizeof(*chain));
44     llist_append(&listener_chain, &chain->chain);
45
46     chain->evt_cb = listener;
47 }
48
49 int
50 __input_dev_read(struct device* dev, void* buf, size_t offset, size_t len)
51 {
52     struct input_device* idev = dev->underlay;
53
54     if (len < sizeof(struct input_evt_pkt)) {
55         return ERANGE;
56     }
57
58     // wait for new event
59     pwait(&idev->readers);
60
61     memcpy(buf, &idev->current_pkt, sizeof(struct input_evt_pkt));
62
63     return sizeof(struct input_evt_pkt);
64 }
65
66 int
67 __input_dev_read_pg(struct device* dev, void* buf, size_t offset)
68 {
69     return __input_dev_read(dev, buf, offset, PAGE_SIZE);
70 }
71
72 struct input_device*
73 input_add_device(struct devclass* class, char* name_fmt, ...)
74 {
75     assert(input_devcat);
76
77     struct input_device* idev = vzalloc(sizeof(*idev));
78     waitq_init(&idev->readers);
79
80     va_list args;
81     va_start(args, name_fmt);
82
83     struct device* dev = device_allocseq(dev_meta(input_devcat), idev);
84
85     device_setname_vargs(dev_meta(dev), name_fmt, args);
86     register_device(dev, class, NULL);
87
88     idev->dev_if = dev;
89     dev->ops.read = __input_dev_read;
90     dev->ops.read_page = __input_dev_read_pg;
91
92     va_end(args);
93
94     return idev;
95 }