--- /dev/null
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+#include "ozconfig.h"
+#ifdef WANT_EVENT_TRACE
+#include <linux/jiffies.h>
+#include <linux/uaccess.h>
+#include "oztrace.h"
+#include "ozevent.h"
+/*------------------------------------------------------------------------------
+ */
+unsigned long g_evt_mask = 0xffffffff;
+/*------------------------------------------------------------------------------
+ */
+#define OZ_MAX_EVTS    2048    /* Must be power of 2 */
+DEFINE_SPINLOCK(g_eventlock);
+static int g_evt_in;
+static int g_evt_out;
+static int g_missed_events;
+static struct oz_event g_events[OZ_MAX_EVTS];
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+void oz_event_init(void)
+{
+       oz_trace("Event tracing initialized\n");
+       g_evt_in = g_evt_out = 0;
+       g_missed_events = 0;
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+void oz_event_term(void)
+{
+       oz_trace("Event tracing terminated\n");
+}
+/*------------------------------------------------------------------------------
+ * Context: any
+ */
+void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4)
+{
+       unsigned long irqstate;
+       int ix;
+       spin_lock_irqsave(&g_eventlock, irqstate);
+       ix = (g_evt_in + 1) & (OZ_MAX_EVTS - 1);
+       if (ix != g_evt_out) {
+               struct oz_event *e = &g_events[g_evt_in];
+               e->jiffies = jiffies;
+               e->evt = evt;
+               e->ctx1 = ctx1;
+               e->ctx2 = ctx2;
+               e->ctx3 = ctx3;
+               e->ctx4 = ctx4;
+               g_evt_in = ix;
+       } else {
+               g_missed_events++;
+       }
+       spin_unlock_irqrestore(&g_eventlock, irqstate);
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+int oz_events_copy(struct oz_evtlist __user *lst)
+{
+       int first;
+       int ix;
+       struct hdr {
+               int count;
+               int missed;
+       } hdr;
+       ix = g_evt_out;
+       hdr.count = g_evt_in - ix;
+       if (hdr.count < 0)
+               hdr.count += OZ_MAX_EVTS;
+       if (hdr.count > OZ_EVT_LIST_SZ)
+               hdr.count = OZ_EVT_LIST_SZ;
+       hdr.missed = g_missed_events;
+       g_missed_events = 0;
+       if (copy_to_user((void __user *)lst, &hdr, sizeof(hdr)))
+               return -EFAULT;
+       first = OZ_MAX_EVTS - ix;
+       if (first > hdr.count)
+               first = hdr.count;
+       if (first) {
+               int sz = first*sizeof(struct oz_event);
+               void __user *p = (void __user *)lst->evts;
+               if (copy_to_user(p, &g_events[ix], sz))
+                       return -EFAULT;
+               if (hdr.count > first) {
+                       p = (void __user *)&lst->evts[first];
+                       sz = (hdr.count-first)*sizeof(struct oz_event);
+                       if (copy_to_user(p, g_events, sz))
+                               return -EFAULT;
+               }
+       }
+       ix += hdr.count;
+       if (ix >= OZ_MAX_EVTS)
+               ix -= OZ_MAX_EVTS;
+       g_evt_out = ix;
+       return 0;
+}
+/*------------------------------------------------------------------------------
+ * Context: process
+ */
+void oz_events_clear(void)
+{
+       unsigned long irqstate;
+       spin_lock_irqsave(&g_eventlock, irqstate);
+       g_evt_in = g_evt_out = 0;
+       g_missed_events = 0;
+       spin_unlock_irqrestore(&g_eventlock, irqstate);
+}
+#endif /* WANT_EVENT_TRACE */
+
 
--- /dev/null
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+#ifndef _OZEVENT_H
+#define _OZEVENT_H
+#include "ozconfig.h"
+#include "ozeventdef.h"
+
+#ifdef WANT_EVENT_TRACE
+extern unsigned long g_evt_mask;
+void oz_event_init(void);
+void oz_event_term(void);
+void oz_event_log2(u8 evt, u8 ctx1, u16 ctx2, void *ctx3, unsigned ctx4);
+#define oz_event_log(__evt, __ctx1, __ctx2, __ctx3, __ctx4) \
+       do { \
+               if ((1<<(__evt)) & g_evt_mask) \
+                       oz_event_log2(__evt, __ctx1, __ctx2, __ctx3, __ctx4); \
+       } while (0)
+int oz_events_copy(struct oz_evtlist __user *lst);
+void oz_events_clear(void);
+#else
+#define oz_event_init()
+#define oz_event_term()
+#define oz_event_log(__evt, __ctx1, __ctx2, __ctx3, __ctx4)
+#define oz_events_copy(__lst)
+#define oz_events_clear()
+#endif /* WANT_EVENT_TRACE */
+
+#endif /* _OZEVENT_H */
 
--- /dev/null
+/* -----------------------------------------------------------------------------
+ * Copyright (c) 2011 Ozmo Inc
+ * Released under the GNU General Public License Version 2 (GPLv2).
+ * -----------------------------------------------------------------------------
+ */
+#ifndef _OZEVENTDEF_H
+#define _OZEVENTDEF_H
+
+#define OZ_EVT_RX_FRAME                0
+#define OZ_EVT_RX_PROCESS      1
+#define OZ_EVT_TX_FRAME                2
+#define OZ_EVT_TX_ISOC         3
+#define OZ_EVT_URB_SUBMIT      4
+#define OZ_EVT_URB_DONE                5
+#define OZ_EVT_URB_CANCEL      6
+#define OZ_EVT_CTRL_REQ                7
+#define OZ_EVT_CTRL_CNF                8
+#define OZ_EVT_CTRL_LOCAL      9
+#define OZ_EVT_CONNECT_REQ     10
+#define OZ_EVT_CONNECT_RSP     11
+#define OZ_EVT_EP_CREDIT       12
+#define OZ_EVT_EP_BUFFERING    13
+#define OZ_EVT_TX_ISOC_DONE    14
+#define OZ_EVT_TX_ISOC_DROP    15
+#define OZ_EVT_TIMER_CTRL      16
+#define OZ_EVT_TIMER           17
+#define OZ_EVT_PD_STATE                18
+#define OZ_EVT_SERVICE         19
+#define OZ_EVT_DEBUG           20
+
+struct oz_event {
+       unsigned long jiffies;
+       unsigned char evt;
+       unsigned char ctx1;
+       unsigned short ctx2;
+       void *ctx3;
+       unsigned ctx4;
+};
+
+#define OZ_EVT_LIST_SZ 256
+struct oz_evtlist {
+       int count;
+       int missed;
+       struct oz_event evts[OZ_EVT_LIST_SZ];
+};
+
+#endif /* _OZEVENTDEF_H */