aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/susb/dwc_common_port/dwc_notifier.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/susb/dwc_common_port/dwc_notifier.h')
-rw-r--r--drivers/usb/susb/dwc_common_port/dwc_notifier.h122
1 files changed, 122 insertions, 0 deletions
diff --git a/drivers/usb/susb/dwc_common_port/dwc_notifier.h b/drivers/usb/susb/dwc_common_port/dwc_notifier.h
new file mode 100644
index 00000000000..4a8cdfe565b
--- /dev/null
+++ b/drivers/usb/susb/dwc_common_port/dwc_notifier.h
@@ -0,0 +1,122 @@
+
+#ifndef __DWC_NOTIFIER_H__
+#define __DWC_NOTIFIER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "dwc_os.h"
+
+/** @file
+ *
+ * A simple implementation of the Observer pattern. Any "module" can
+ * register as an observer or notifier. The notion of "module" is abstract and
+ * can mean anything used to identify either an observer or notifier. Usually
+ * it will be a pointer to a data structure which contains some state, ie an
+ * object.
+ *
+ * Before any notifiers can be added, the global notification manager must be
+ * brought up with dwc_alloc_notification_manager().
+ * dwc_free_notification_manager() will bring it down and free all resources.
+ * These would typically be called upon module load and unload. The
+ * notification manager is a single global instance that handles all registered
+ * observable modules and observers so this should be done only once.
+ *
+ * A module can be observable by using Notifications to publicize some general
+ * information about it's state or operation. It does not care who listens, or
+ * even if anyone listens, or what they do with the information. The observable
+ * modules do not need to know any information about it's observers or their
+ * interface, or their state or data.
+ *
+ * Any module can register to emit Notifications. It should publish a list of
+ * notifications that it can emit and their behavior, such as when they will get
+ * triggered, and what information will be provided to the observer. Then it
+ * should register itself as an observable module. See dwc_register_notifier().
+ *
+ * Any module can observe any observable, registered module, provided it has a
+ * handle to the other module and knows what notifications to observe. See
+ * dwc_add_observer().
+ *
+ * A function of type dwc_notifier_callback_t is called whenever a notification
+ * is triggered with one or more observers observing it. This function is
+ * called in it's own process so it may sleep or block if needed. It is
+ * guaranteed to be called sometime after the notification has occurred and will
+ * be called once per each time the notification is triggered. It will NOT be
+ * called in the same process context used to trigger the notification.
+ *
+ * @section Limitiations
+ *
+ * Keep in mind that Notifications that can be triggered in rapid sucession may
+ * schedule too many processes too handle. Be aware of this limitation when
+ * designing to use notifications, and only add notifications for appropriate
+ * observable information.
+ *
+ * Also Notification callbacks are not synchronous. If you need to synchronize
+ * the behavior between module/observer you must use other means. And perhaps
+ * that will mean Notifications are not the proper solution.
+ */
+
+struct dwc_notifier;
+typedef struct dwc_notifier dwc_notifier_t;
+
+/** The callback function must be of this type.
+ *
+ * @param object This is the object that is being observed.
+ * @param notification This is the notification that was triggered.
+ * @param observer This is the observer
+ * @param notification_data This is notification-specific data that the notifier
+ * has included in this notification. The value of this should be published in
+ * the documentation of the observable module with the notifications.
+ * @param user_data This is any custom data that the observer provided when
+ * adding itself as an observer to the notification. */
+typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer,
+ void *notification_data, void *user_data);
+
+/** Brings up the notification manager. */
+extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx);
+/** Brings down the notification manager. */
+extern void dwc_free_notification_manager(void);
+
+/** This function registers an observable module. A dwc_notifier_t object is
+ * returned to the observable module. This is an opaque object that is used by
+ * the observable module to trigger notifications. This object should only be
+ * accessible to functions that are authorized to trigger notifications for this
+ * module. Observers do not need this object. */
+extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object);
+
+/** This function unregisters an observable module. All observers have to be
+ * removed prior to unregistration. */
+extern void dwc_unregister_notifier(dwc_notifier_t *notifier);
+
+/** Add a module as an observer to the observable module. The observable module
+ * needs to have previously registered with the notification manager.
+ *
+ * @param observer The observer module
+ * @param object The module to observe
+ * @param notification The notification to observe
+ * @param callback The callback function to call
+ * @param user_data Any additional user data to pass into the callback function */
+extern int dwc_add_observer(void *observer, void *object, char *notification,
+ dwc_notifier_callback_t callback, void *user_data);
+
+/** Removes the specified observer from all notifications that it is currently
+ * observing. */
+extern int dwc_remove_observer(void *observer);
+
+/** This function triggers a Notification. It should be called by the
+ * observable module, or any module or library which the observable module
+ * allows to trigger notification on it's behalf. Such as the dwc_cc_t.
+ *
+ * dwc_notify is a non-blocking function. Callbacks are scheduled called in
+ * their own process context for each trigger. Callbacks can be blocking.
+ * dwc_notify can be called from interrupt context if needed.
+ *
+ */
+void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DWC_NOTIFIER_H__ */