summaryrefslogtreecommitdiffstats
path: root/src/fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fsm.c')
-rw-r--r--src/fsm.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/fsm.c b/src/fsm.c
new file mode 100644
index 0000000..f56c857
--- /dev/null
+++ b/src/fsm.c
@@ -0,0 +1,127 @@
+
+#include <asm/errno.h>
+
+#include "intf.h"
+#include "trans.h"
+
+
+static int process_release(struct tsnif_handle *h, struct tsnif_term *term)
+{
+ if (!h->ops || !h->ops->cb_release)
+ return -1;
+
+ return h->ops->cb_release(term);
+}
+
+static int process_error(struct tsnif_handle *h, struct tsnif_term *term, int err)
+{
+ if (!h->ops || !h->ops->cb_err)
+ return -1;
+
+ return h->ops->cb_err(term, err);
+}
+
+static int process_tgroup(struct tsnif_handle *h, struct tsnif_term *term,
+ int group)
+{
+ int err;
+
+ err = trans_group(&h->trans, group);
+ term->state = err ? TSNIF_INTF_STATE_DONE : TSNIF_INTF_STATE_DATA;
+
+ TSNIF_DEBUG("adding group %d, err %d\n", group, err);
+ return err;
+}
+
+static int new(struct tsnif_handle *h,
+ struct tsnif_term *term,
+ struct trans_msg *msg)
+{
+ int err = 0;
+
+ switch(msg->cmd) {
+ case TSNIF_CMD_TGROUP:
+ err = process_tgroup(h, term, msg->group);
+ break;
+
+ case TSNIF_CMD_RELEASE:
+ err = process_release(h, term);
+ break;
+
+ case TSNIF_CMD_ATTACH:
+ /* got ATTACH cmd without error ??? */
+ err = -EINVAL;
+ if (msg->err)
+ break;
+
+ err = process_error(h, term, msg->error);
+ break;
+
+ default:
+ return -1;
+ }
+
+ return err;
+}
+
+static int process_data(struct tsnif_handle *h,
+ struct tsnif_term *term,
+ struct trans_msg *msg)
+{
+ struct tsnif_data data;
+
+ TSNIF_DEBUG("type %d, idx %d\n",
+ term->type, term->idx);
+
+ if (!h->ops || !h->ops->cb_data)
+ return -1;
+
+ data.ptr = msg->data.ptr;
+ data.len = msg->data.len;
+ data.flags = msg->data.flags;
+
+ return h->ops->cb_data(term, &data);
+}
+
+static int data(struct tsnif_handle *h,
+ struct tsnif_term *term,
+ struct trans_msg *msg)
+{
+ int err = 0;
+
+ switch(msg->cmd) {
+ case TSNIF_CMD_RELEASE:
+ err = process_release(h, term);
+ break;
+
+ case TSNIF_CMD_DATA:
+ err = process_data(h, term, msg);
+ break;
+
+ default:
+ return -1;
+ }
+
+ return err;
+}
+
+int fsm_process(struct tsnif_handle *h,
+ struct tsnif_term *term,
+ struct trans_msg *msg)
+{
+ TSNIF_DEBUG("got cmd %d for term type %d, idx %d, state %d\n",
+ msg->cmd, term->type, term->idx, term->state);
+
+ switch(term->state) {
+ case TSNIF_INTF_STATE_NEW:
+ return new(h, term, msg);
+
+ case TSNIF_INTF_STATE_DATA:
+ return data(h, term, msg);
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}