1 /* 2 * Provide access to keypad events on the configured device. 3 * 4 * (c) 2018 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/devices/dataspace.h> 23 #include "input-event-client.h" 24 #include "input-event-server.h" 25 #include "input-event-ops.h" 26 #include "input-keypad-client.h" 27 28 #include <l4/cxx/ipc_stream> 29 #include <l4/re/dataspace> 30 #include <l4/re/env> 31 #include <l4/re/event> 32 #include <l4/re/util/cap_alloc> 33 #include <l4/re/util/object_registry> 34 #include <l4/sys/capability> 35 #include <l4/sys/icu> 36 #include <l4/sys/kip.h> 37 #include <l4/sys/types.h> 38 #include <l4/util/util.h> 39 40 /* Handle invocations. */ 41 42 int 43 Input_event_server::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios) 44 { 45 l4_msgtag_t tag; 46 l4_umword_t op; 47 48 (void) obj; 49 ios >> tag; 50 51 switch (tag.label()) 52 { 53 case L4::Meta::Protocol: 54 return L4::Util::handle_meta_request<Input_event_interface>(ios); 55 56 case L4RE_PROTO_EVENT: 57 ios >> op; 58 switch (op) 59 { 60 /* Reset the buffer state and return the buffer memory capability. */ 61 62 case Input_event_op_get_buffer: 63 _events.reset(); 64 ios << _mem; 65 return L4_EOK; 66 67 default: 68 return -L4_ENOSYS; 69 } 70 71 case L4_PROTO_IRQ: 72 ios >> op; 73 switch (op) 74 { 75 /* Just return the interrupt capability. */ 76 77 case Input_event_op_bind: 78 ios << _irq; 79 return L4_EOK; 80 81 default: 82 return -L4_ENOSYS; 83 } 84 85 default: 86 return -L4_EBADPROTO; 87 } 88 } 89 90 91 92 /* Event sending methods. */ 93 94 void 95 Input_event_server::send_event(int type, int code, int value) 96 { 97 L4Re::Event_buffer::Event event; 98 99 event.time = l4_kip_clock(l4re_kip()); 100 event.payload.stream_id = 0; 101 event.payload.type = type; 102 event.payload.code = code; 103 event.payload.value = value; 104 105 /* Queue the event and trigger the interrupt. */ 106 107 _events.put(event); 108 _irq->trigger(); 109 } 110 111 112 113 static void handler(Input_event event, void *priv) 114 { 115 Input_event_server *server = (Input_event_server *) priv; 116 117 server->send_event(event.type, event.code, event.value); 118 } 119 120 121 122 static L4Re::Util::Registry_server<> server; 123 124 125 126 int run(void) 127 { 128 Keypad *keypad = Keypad::get_keypad(); 129 Input_keypad_client client(keypad); 130 void *buffer; 131 132 // Memory allocation capability for the event data. 133 134 L4::Cap<L4Re::Dataspace> mem = allocate_data(L4_PAGESIZE, &buffer); 135 if (!mem.is_valid()) return 1; 136 137 /* Obtain a capability for the interrupt. */ 138 139 L4::Cap<L4::Irq> irq = L4Re::Util::cap_alloc.alloc<L4::Irq>(); 140 if (!irq.is_valid()) return 1; 141 142 /* Create an interrupt object. */ 143 144 if (l4_error(L4Re::Env::env()->factory()->create(irq))) return 1; 145 146 // Event buffer for the data. 147 148 L4Re::Event_buffer events(buffer, L4_PAGESIZE); 149 150 // Initialise and register a server object. 151 152 Input_event_server server_obj(mem, irq, events); 153 server.registry()->register_obj(&server_obj, "ev"); 154 155 // Attach the event handler and wait for events. 156 157 client.attach(handler, (void *) &server_obj); 158 159 // Enter the IPC server loop. 160 161 server.loop(); 162 return 0; 163 }