diff --git a/examples/cpp/cp_app.cpp b/examples/cpp/cp_app.cpp index 5b74ffa7..74700137 100644 --- a/examples/cpp/cp_app.cpp +++ b/examples/cpp/cp_app.cpp @@ -50,12 +50,22 @@ static struct osdp_channel cp_channel = { .close = nullptr, }; -int event_handler(void *data, int pd, struct osdp_event *event) { - (void)(data); +class EventHandler : public OSDP::ControlPanelEventHandler +{ +private: + const char* _message; +public: + explicit EventHandler(const char* message) : _message{message} {} - std::cout << "PD" << pd << " EVENT: " << event->type << std::endl; - return 0; -} + int event_handler(const OSDP::ControlPanel& cp, + int pd, struct osdp_event *event) override + { + (void)(cp); + std::cout << "PD " << pd << " EVENT: " << event->type << std::endl; + std::cout << _message << std::endl; + return 0; + } +}; int main() { @@ -65,11 +75,12 @@ int main() cp.setup(&cp_channel, 1, pd_info); - cp.set_event_callback(event_handler, nullptr); + EventHandler handler { "Hello world!" }; + + cp.set_event_callback(&handler); while (1) { // your application code. - cp.refresh(); std::this_thread::sleep_for(std::chrono::microseconds(10 * 1000)); } diff --git a/examples/platformio/cp.ino b/examples/platformio/cp.ino index 6981021e..bdb4b3c0 100644 --- a/examples/platformio/cp.ino +++ b/examples/platformio/cp.ino @@ -58,13 +58,23 @@ void init_cp_info() cp_channel.send = serial1_send_func; } -int event_handler(void *data, int pd, struct osdp_event *event) +class EventHandler : public OSDP::ControlPanelEventHandler { - (void)(data); +private: + const char* _message; +public: + explicit EventHandler(const char* message) : _message{message} {} - Serial.println("Received an event!"); - return 0; -} + int event_handler(const OSDP::ControlPanel& cp, + int pd, struct osdp_event *event) override + { + (void)(cp); + (void)(pd); + (void)(event); + Serial.println("Received an event!"); + return 0; + } +}; void setup() { @@ -75,7 +85,9 @@ void setup() init_cp_info(); cp.setup(&cp_channel, 1, pd_info); - cp.set_event_callback(event_handler, nullptr); + + EventHandler handler { "Hello world!" }; + cp.set_event_callback(&handler); } void loop() diff --git a/include/osdp.h b/include/osdp.h index 86d0c972..6515b430 100644 --- a/include/osdp.h +++ b/include/osdp.h @@ -1025,6 +1025,8 @@ typedef int (*pd_command_callback_t)(void *arg, struct osdp_cmd *cmd); * * @param arg Opaque pointer provided by the application during callback * registration. + * @param ctx OSDP context, can be used to retrieve additional + * PD information. * @param pd PD offset (0-indexed) of this PD in `osdp_pd_info_t *` passed to * osdp_cp_setup() * @param ev pointer to osdp_event struct (filled by libosdp). @@ -1032,7 +1034,8 @@ typedef int (*pd_command_callback_t)(void *arg, struct osdp_cmd *cmd); * @retval 0 on handling the event successfully. * @retval -ve on errors. */ -typedef int (*cp_event_callback_t)(void *arg, int pd, struct osdp_event *ev); +typedef int (*cp_event_callback_t)(void *arg, const osdp_t *ctx, int pd, + struct osdp_event *ev); /** * @brief Terminal status of a submitted command/event object. diff --git a/include/osdp.hpp b/include/osdp.hpp index 88a21e8d..9d0aabaa 100644 --- a/include/osdp.hpp +++ b/include/osdp.hpp @@ -32,22 +32,22 @@ class OSDP_EXPORT Common { osdp_set_log_callback(cb); } - const char *get_version() + const char *get_version() const { return osdp_get_version(); } - const char *get_source_info() + const char *get_source_info() const { return osdp_get_source_info(); } - void get_status_mask(uint8_t *bitmask) + void get_status_mask(uint8_t *bitmask) const { osdp_get_status_mask(_ctx, bitmask); } - void get_sc_status_mask(uint8_t *bitmask) + void get_sc_status_mask(uint8_t *bitmask) const { osdp_get_sc_status_mask(_ctx, bitmask); } @@ -57,7 +57,7 @@ class OSDP_EXPORT Common { return osdp_file_register_ops(_ctx, pd, ops); } - int file_tx_get_status(int pd, int *size, int *offset) + int file_tx_get_status(int pd, int *size, int *offset) const { return osdp_get_file_tx_status(_ctx, pd, size, offset); } @@ -71,6 +71,13 @@ class OSDP_EXPORT Common { osdp_t *_ctx; }; +class ControlPanel; + +class OSDP_EXPORT ControlPanelEventHandler { +public: + virtual int event_handler(const ControlPanel& cp, int pd, struct osdp_event *ev) = 0; +}; + class OSDP_EXPORT ControlPanel : public Common { public: ControlPanel() {} @@ -101,7 +108,7 @@ class OSDP_EXPORT ControlPanel : public Common { return false; } - int add_pd(int num_pd, const osdp_pd_info_t *info) + int add_pd(int num_pd, const osdp_pd_info_t *info) const { return osdp_cp_add_pd(_ctx, num_pd, info); } @@ -127,9 +134,9 @@ class OSDP_EXPORT ControlPanel : public Common { return osdp_cp_flush_commands(_ctx, pd); } - void set_event_callback(cp_event_callback_t cb, void *arg) + void set_event_callback(ControlPanelEventHandler *cb) { - osdp_cp_set_event_callback(_ctx, cb, arg); + osdp_cp_set_event_callback(_ctx, ControlPanel::event_callback, cb); } void set_command_completion_callback(cp_command_completion_callback_t cb, @@ -138,12 +145,12 @@ class OSDP_EXPORT ControlPanel : public Common { osdp_cp_set_command_completion_callback(_ctx, cb, arg); } - int get_pd_id(int pd, struct osdp_pd_id *id) + int get_pd_id(int pd, struct osdp_pd_id *id) const { return osdp_cp_get_pd_id(_ctx, pd, id); } - int get_capability(int pd, struct osdp_pd_cap *cap) + int get_capability(int pd, struct osdp_pd_cap *cap) const { return osdp_cp_get_capability(_ctx, pd, cap); } @@ -163,11 +170,22 @@ class OSDP_EXPORT ControlPanel : public Common { return osdp_cp_enable_pd(_ctx, pd); } - bool is_pd_enabled(int pd) + bool is_pd_enabled(int pd) const { return osdp_cp_is_pd_enabled(_ctx, pd); } +private: + static int event_callback(void *arg, const osdp_t *ctx, int pd, + struct osdp_event *ev) + { + ControlPanel cp; + cp._ctx = const_cast(ctx); + int result = static_cast(arg) + ->event_handler(const_cast(cp), pd, ev); + cp._ctx = nullptr; + return result; + } }; class OSDP_EXPORT PeripheralDevice : public Common { diff --git a/python/osdp_sys/cp.c b/python/osdp_sys/cp.c index 1b6fe90c..43e9c32d 100644 --- a/python/osdp_sys/cp.c +++ b/python/osdp_sys/cp.c @@ -69,8 +69,10 @@ static PyObject *pyosdp_cp_sc_status(pyosdp_cp_t *self, PyObject *args) return Py_BuildValue("I", bitmask); } -int pyosdp_cp_event_cb(void *data, int address, struct osdp_event *event) +int pyosdp_cp_event_cb(void *data, const osdp_t* ctx, int address, struct osdp_event *event) { + (void)(ctx); + pyosdp_cp_t *self = data; PyObject *arglist, *result, *event_dict; diff --git a/src/osdp_cp.c b/src/osdp_cp.c index ba2081ec..73f1c2c8 100644 --- a/src/osdp_cp.c +++ b/src/osdp_cp.c @@ -58,10 +58,10 @@ enum osdp_cp_error_e { static void cp_dispatch_event(struct osdp_pd *pd, const struct osdp_event *event) { - struct osdp *ctx = pd_to_osdp(pd); + const struct osdp *ctx = pd_to_osdp(pd); if (ctx->event_callback) { - ctx->event_callback(ctx->event_callback_arg, pd->idx, + ctx->event_callback(ctx->event_callback_arg, ctx, pd->idx, (struct osdp_event *)event); osdp_metrics_report(pd, OSDP_METRIC_EVENT); } @@ -966,7 +966,7 @@ static int cp_get_online_command(struct osdp_pd *pd) static void notify_pd_status(struct osdp_pd *pd, bool is_online) { - struct osdp *ctx = pd_to_osdp(pd); + const struct osdp *ctx = pd_to_osdp(pd); struct osdp_event evt; if (!ctx->event_callback || !is_notifications_enabled(pd)) { @@ -976,13 +976,13 @@ static void notify_pd_status(struct osdp_pd *pd, bool is_online) evt.type = OSDP_EVENT_NOTIFICATION; evt.notif.type = OSDP_NOTIFICATION_PD_STATUS; evt.notif.arg0 = is_online; - ctx->event_callback(ctx->event_callback_arg, pd->idx, &evt); + ctx->event_callback(ctx->event_callback_arg, ctx, pd->idx, &evt); osdp_metrics_report(pd, OSDP_METRIC_EVENT); } static void notify_sc_status(struct osdp_pd *pd) { - struct osdp *ctx = pd_to_osdp(pd); + const struct osdp *ctx = pd_to_osdp(pd); struct osdp_event evt; if (!ctx->event_callback || !is_notifications_enabled(pd)) { @@ -993,14 +993,14 @@ static void notify_sc_status(struct osdp_pd *pd) evt.notif.type = OSDP_NOTIFICATION_SC_STATUS; evt.notif.arg0 = sc_is_active(pd); evt.notif.arg1 = sc_use_scbkd(pd); - ctx->event_callback(ctx->event_callback_arg, pd->idx, &evt); + ctx->event_callback(ctx->event_callback_arg, ctx, pd->idx, &evt); osdp_metrics_report(pd, OSDP_METRIC_EVENT); } void osdp_file_tx_notify_done(struct osdp_pd *pd, int file_id, enum osdp_file_tx_outcome outcome) { - struct osdp *ctx = pd_to_osdp(pd); + const struct osdp *ctx = pd_to_osdp(pd); struct osdp_event evt; if (!ctx->event_callback || !is_notifications_enabled(pd)) { @@ -1011,7 +1011,7 @@ void osdp_file_tx_notify_done(struct osdp_pd *pd, int file_id, evt.notif.type = OSDP_NOTIFICATION_FILE_TX_DONE; evt.notif.arg0 = file_id; evt.notif.arg1 = outcome; - ctx->event_callback(ctx->event_callback_arg, pd->idx, &evt); + ctx->event_callback(ctx->event_callback_arg, ctx, pd->idx, &evt); osdp_metrics_report(pd, OSDP_METRIC_EVENT); } @@ -1280,7 +1280,7 @@ static void notify_command_status(struct osdp_pd *pd, int status) { int app_cmd; struct osdp_event evt; - struct osdp *ctx = pd_to_osdp(pd); + const struct osdp *ctx = pd_to_osdp(pd); if (!ctx->event_callback || !is_notifications_enabled(pd)) { return; @@ -1317,7 +1317,7 @@ static void notify_command_status(struct osdp_pd *pd, int status) evt.notif.arg0 = app_cmd; evt.notif.arg1 = status ? 0 : -1; - ctx->event_callback(ctx->event_callback_arg, pd->idx, &evt); + ctx->event_callback(ctx->event_callback_arg, ctx, pd->idx, &evt); osdp_metrics_report(pd, OSDP_METRIC_EVENT); } diff --git a/tests/unit-tests/test-async-fuzz.c b/tests/unit-tests/test-async-fuzz.c index 34f2bd2c..38454647 100644 --- a/tests/unit-tests/test-async-fuzz.c +++ b/tests/unit-tests/test-async-fuzz.c @@ -27,11 +27,12 @@ struct async_test_data { bool event_generated; }; -static int async_event_callback(void *data, int pd, struct osdp_event *event) +static int async_event_callback(void *data, const osdp_t *ctx, int pd, struct osdp_event *event) { struct async_test_data *d = data; ARG_UNUSED(pd); + ARG_UNUSED(ctx); if (event->type == OSDP_EVENT_CARDREAD) { d->event_generated = true; } diff --git a/tests/unit-tests/test-commands.c b/tests/unit-tests/test-commands.c index ffde639c..0912367f 100644 --- a/tests/unit-tests/test-commands.c +++ b/tests/unit-tests/test-commands.c @@ -40,8 +40,9 @@ struct test_command_ctx { static struct test_command_ctx g_test_ctx = {0}; -int test_commands_event_callback(void *arg, int pd, struct osdp_event *ev) +int test_commands_event_callback(void *arg, const osdp_t* cp_ctx, int pd, struct osdp_event *ev) { + ARG_UNUSED(cp_ctx); ARG_UNUSED(pd); struct test_command_ctx *ctx = arg; diff --git a/tests/unit-tests/test-events.c b/tests/unit-tests/test-events.c index 0296d61b..9e8170f6 100644 --- a/tests/unit-tests/test-events.c +++ b/tests/unit-tests/test-events.c @@ -28,9 +28,10 @@ struct test_event_ctx { static struct test_event_ctx g_test_ctx = {0}; -int test_events_event_callback(void *arg, int pd, struct osdp_event *ev) +int test_events_event_callback(void *arg, const osdp_t *cp_ctx, int pd, struct osdp_event *ev) { ARG_UNUSED(pd); + ARG_UNUSED(cp_ctx); struct test_event_ctx *ctx = arg; ctx->event_seen = true; diff --git a/tests/unit-tests/test-file.c b/tests/unit-tests/test-file.c index 6991be2c..0824fccd 100644 --- a/tests/unit-tests/test-file.c +++ b/tests/unit-tests/test-file.c @@ -169,10 +169,11 @@ struct file_tx_notification { static struct file_tx_notification g_notif; -static int event_callback(void *arg, int pd, struct osdp_event *ev) +static int event_callback(void *arg, const osdp_t *ctx, int pd, struct osdp_event *ev) { ARG_UNUSED(arg); ARG_UNUSED(pd); + ARG_UNUSED(ctx); if (ev->type != OSDP_EVENT_NOTIFICATION) { return 0; diff --git a/tests/unit-tests/test-hotplug.c b/tests/unit-tests/test-hotplug.c index 1a7bf140..40a79a4a 100644 --- a/tests/unit-tests/test-hotplug.c +++ b/tests/unit-tests/test-hotplug.c @@ -33,9 +33,10 @@ static struct test_hotplug_ctx g_test_ctx = {0}; static bool wait_for_pd_online(int timeout_sec); -int test_hotplug_event_callback(void *arg, int pd, struct osdp_event *ev) +int test_hotplug_event_callback(void *arg, const osdp_t *cp_ctx, int pd, struct osdp_event *ev) { ARG_UNUSED(pd); + ARG_UNUSED(cp_ctx); struct test_hotplug_ctx *ctx = arg; ctx->event_seen = true; diff --git a/tests/unit-tests/test-notifications.c b/tests/unit-tests/test-notifications.c index 37c3500c..8fa6c6a6 100644 --- a/tests/unit-tests/test-notifications.c +++ b/tests/unit-tests/test-notifications.c @@ -78,11 +78,12 @@ static int pd_cmd_cb(void *arg, struct osdp_cmd *cmd) return 0; } -static int cp_event_cb(void *arg, int pd, struct osdp_event *ev) +static int cp_event_cb(void *arg, const osdp_t *ctx, int pd, struct osdp_event *ev) { struct notif_ctx *nx = arg; ARG_UNUSED(pd); + ARG_UNUSED(ctx); if (ev->type != OSDP_EVENT_NOTIFICATION) { return 0;