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 47 (void) obj; 48 ios >> tag; 49 50 switch (tag.label()) 51 { 52 case L4::Meta::Protocol: 53 return L4::Util::handle_meta_request<Input_event_interface>(ios); 54 55 /* Reset the buffer state and return the buffer memory capability. */ 56 57 case Input_event_op_get_buffer: 58 _events.reset(); 59 ios << _mem; 60 return L4_EOK; 61 62 /* Just return the interrupt capability. */ 63 64 case Input_event_op_bind: 65 ios << _irq; 66 return L4_EOK; 67 68 default: 69 return -L4_EBADPROTO; 70 } 71 } 72 73 74 75 /* Event sending methods. */ 76 77 void 78 Input_event_server::send_event(int type, int code, int value) 79 { 80 L4Re::Event_buffer::Event event; 81 82 event.time = l4_kip_clock(l4re_kip()); 83 event.payload.stream_id = 0; 84 event.payload.type = type; 85 event.payload.code = code; 86 event.payload.value = value; 87 88 /* Queue the event and trigger the interrupt. */ 89 90 _events.put(event); 91 _irq->trigger(); 92 } 93 94 95 96 static void handler(Input_event event, void *priv) 97 { 98 Input_event_server *server = (Input_event_server *) priv; 99 100 server->send_event(event.type, event.code, event.value); 101 } 102 103 104 105 static L4Re::Util::Registry_server<> server; 106 107 108 109 int run(void) 110 { 111 Keypad *keypad = Keypad::get_keypad(); 112 Input_keypad_client client(keypad); 113 void *buffer; 114 115 // Memory allocation capability for the event data. 116 117 L4::Cap<L4Re::Dataspace> mem = allocate_data(L4_PAGESIZE, &buffer); 118 if (!mem.is_valid()) return 1; 119 120 /* Obtain a capability for the interrupt. */ 121 122 L4::Cap<L4::Irq> irq = L4Re::Util::cap_alloc.alloc<L4::Irq>(); 123 if (!irq.is_valid()) return 1; 124 125 /* Create an interrupt object. */ 126 127 if (l4_error(L4Re::Env::env()->factory()->create(irq))) return 1; 128 129 // Event buffer for the data. 130 131 L4Re::Event_buffer events(buffer, L4_PAGESIZE); 132 133 // Initialise and register a server object. 134 135 Input_event_server server_obj(mem, irq, events); 136 server.registry()->register_obj(&server_obj, "ev"); 137 138 // Attach the event handler and wait for events. 139 140 client.attach(handler, (void *) &server_obj); 141 142 // Enter the IPC server loop. 143 144 server.loop(); 145 return 0; 146 }