1 /* 2 * Copyright (c) 2020, Google, Inc. All rights reserved 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files 6 * (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, 10 * subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24 #pragma once 25 26 #include <list.h> 27 #include <reflist.h> 28 #include <stdint.h> 29 #include <sys/types.h> 30 31 #include <kernel/spinlock.h> 32 #include <lib/trusty/handle.h> 33 #include <lib/trusty/uuid.h> 34 #include <uapi/trusty_uevent.h> 35 36 /** 37 * struct event_source_ops - user provided callbacks for event source 38 * @open: invoked when the first client connects to event source 39 * @mask: invoked to mask underlying event source 40 * @unmask: invoked to unmask underlying events source 41 * @close: invoked when the last client connected to event source 42 * goes away 43 * 44 * Note: The @open and @close callbacks are invoked with global mutex held 45 * so it is not allowed to create or close another event in that context. 46 * The @mask and @unmask callback are invoked in context with spinlock 47 * (private to event source obejct) held and interrupts disabled. 48 */ 49 struct event_source_ops { 50 void (*open)(const void* priv); 51 void (*mask)(const void* priv); 52 void (*unmask)(const void* priv); 53 void (*close)(const void* priv); 54 }; 55 56 /** 57 * event_source_create() - create new event source object 58 * @name: name of the object to create (non-empty string) 59 * @ops: pointer to &struct event_source_ops 60 * @ops_arg: @priv argument of callbacks specified by @ops parameeter 61 * @uuids: pointer to array of &struct uuids that represents client 62 * uuids that are allowed to connect to event source object 63 * @uuids_num: number of entries in array pointed by @uuids parameter 64 * @flags: reserved, must be set to 0 65 * @ph: pointer to &struct handle to return handle to caller 66 * 67 * Note1: in general @ops are optional. 68 * 69 * Note2: if @ops are present both &struct event_source_ops->open and 70 * &struct event_source_ops->close callbacks must be provided. 71 * 72 * Note3: if &struct event_source_ops->mask callback is provided corresponding 73 * &struct event_source_ops->unmask callback must be provided too. 74 * 75 * Note4: the retains an ownership of memory referenced by @name, @ops, 76 * @ops_arg and @uuids parameters and should keep this memory around for event 77 * source object duration. This memory should be only freed after the last 78 * reference to event source handle had been closed. 79 * 80 * Return: 0 on success, negative error otherwise 81 */ 82 int event_source_create(const char* name, 83 const struct event_source_ops* ops, 84 const void* ops_arg, 85 const uuid_t* uuids, 86 unsigned int uuids_num, 87 unsigned int flags, 88 struct handle** ph); 89 90 /** 91 * event_source_publish() - publish event source event 92 * @h: pointer to &struct handle of event source to publish 93 * 94 * This routine makes an event source object (previously created with 95 * event_source_create() call) available for clients. 96 * 97 * Return: 0 on success, negative error otherwise 98 */ 99 int event_source_publish(struct handle* h); 100 101 /** 102 * event_source_open() - open specified event source 103 * @cid: pointer to client's &struct uuid 104 * @name: pointer to buffer containing event source name 105 * @max_name: max size of the buffer containing name 106 * @flags: reserved, must be zero 107 * @ph: pointer to &struct handle to return handle to caller 108 * 109 * Return: 0 on success, negative error otherwise 110 */ 111 int event_source_open(const struct uuid* cid, 112 const char* name, 113 size_t max_name, 114 unsigned int flags, 115 struct handle** ph); 116 117 /** 118 * event_source_signal() - signal event source 119 * @h: pointer to &struct handle to signal 120 * 121 * Note1: It is safe to call this routine from interrupt context. 122 * 123 * Note2: if underlying event source object implements 124 * &struct event_source_ops->mask callback it is illegal to call this routine 125 * again for objects that are already in signaled state. (It is expected that 126 * event source is masked which should prevent signaling it again). For this 127 * schema it is guaranteed that all clients would see an event exactly once for 128 * each invocation of event_source_signal() routine. 129 * 130 * Note: for all other valid callback combinations, it is OK to call this 131 * routine multiple times in any state, but some events might be lost. This is 132 * similar to receiving a new edge triggered interrupt while previous one is 133 * not handled yet. It is also guaranteed that all clients will be notified 134 * after the last call to event_source_signal() at least once. 135 * 136 * Return: 0 on success, negative error otherwise 137 */ 138 int event_source_signal(struct handle* h); 139 140 /** 141 * event_client_notify_handled() - change event client state 142 * @h: pointer to &struct handle to change state 143 * 144 * This routine is called on client handle to indicate that the client has 145 * finished handling an event and underlying object has to change it's state 146 * accordingly. 147 * 148 * Return: 0 on success, negative error otherwise 149 */ 150 int event_client_notify_handled(struct handle* h); 151