#include #include "intf.h" #include "list.h" #include "fsm.h" #include "debug.h" static struct tsnif_term *term_find(struct tsnif_handle *h, int type, int idx) { struct tsnif_term *t; list_for_each_entry(t, &h->terms, list) if ((t->type == type) && (t->idx == idx)) return t; return NULL; } static int process_notify(struct tsnif_handle *h, struct trans_msg *msg) { struct tsnif_term term; if (msg->ack) return 0; if (!h->ops || !h->ops->cb_notify) return -1; /* otherwise return fake one */ memset(&term, 0x0, sizeof(term)); term.type = msg->type; term.idx = msg->idx; term.handle = h; term.state = TSNIF_INTF_STATE_NONE; return h->ops->cb_notify(&term, msg->cmd); } static int process_mgroup(struct tsnif_handle *h, struct trans_msg *msg) { if (msg->ack) return 0; return trans_group(&h->trans, msg->group); } static int trans_cb(struct trans_handle *h, struct trans_msg *msg) { struct tsnif_handle *handle; struct tsnif_term *term; TSNIF_DEBUG(INTF, "got cmd %d, type %d, idx %d\n", msg->cmd, msg->type, msg->idx); handle = container_of(h, struct tsnif_handle, trans); /* do we have this term */ term = term_find(handle, msg->type, msg->idx); /* non term related bussines */ switch(msg->cmd) { case TSNIF_CMD_TTY_RELEASE: /* if we are handling the term, * let's fsm do the job */ if (term) break; /* falling throught intentionaly */ case TSNIF_CMD_TTY_CREATE: case TSNIF_CMD_TTY_LIST: return process_notify(handle, msg); case TSNIF_CMD_MGROUP: return process_mgroup(handle, msg); } /* no term no job here */ if (!term) return -ENODEV; return fsm_process(handle, term, msg); } static int init_mgroup(struct tsnif_handle *h) { struct trans_msg msg; TSNIF_DEBUG(INTF, "sending mgroup command\n"); msg.cmd = TSNIF_CMD_MGROUP; return trans_send(&h->trans, &msg); } int tsnif_init(struct tsnif_handle *h, struct tsnif_ops *ops, int trans_flags) { int err; if (!ops) return -EINVAL; memset(h, 0x0, sizeof(*h)); h->ops = ops; INIT_LIST_HEAD(&h->terms); err = trans_init(&h->trans, trans_cb, trans_flags); if (err) return err; return init_mgroup(h); } int tsnif_close(struct tsnif_handle *h) { return trans_close(&h->trans); } int tsnif_process(struct tsnif_handle *h) { return trans_process(&h->trans); } int tsnif_fd(struct tsnif_handle *h) { return trans_fd(&h->trans); } int tsnif_term_add(struct tsnif_handle *h, struct tsnif_term *term, int type, int idx) { struct tsnif_term *t; t = term_find(h, type, idx); if (t) return -EEXIST; memset(term, 0x0, sizeof(*term)); term->type = type; term->idx = idx; term->handle = h; term->state = TSNIF_INTF_STATE_NEW; list_add_tail(&term->list, &h->terms); return 0; } int tsnif_term_del(struct tsnif_handle *h, struct tsnif_term *term) { list_del(&term->list); return 0; } int tsnif_attach(struct tsnif_term *term) { struct trans_msg msg; struct tsnif_handle *h = term->handle; TSNIF_DEBUG(INTF, "type %d, idx %d\n", term->type, term->idx); if (fsm_send(term, TSNIF_CMD_ATTACH)) { TSNIF_DEBUG(INTF, "wrong state (%d) skiping detach\n", term->state); return -1; } msg.type = term->type; msg.idx = term->idx; msg.cmd = TSNIF_CMD_ATTACH; return trans_send(&h->trans, &msg); } int tsnif_detach(struct tsnif_term *term) { struct trans_msg msg; struct tsnif_handle *h = term->handle; TSNIF_DEBUG(INTF, "type %d, idx %d\n", term->type, term->idx); if (fsm_send(term, TSNIF_CMD_DETACH)) { TSNIF_DEBUG(INTF, "wrong state (%d) skiping detach\n", term->state); return -1; } msg.type = term->type; msg.idx = term->idx; msg.cmd = TSNIF_CMD_DETACH; return trans_send(&h->trans, &msg); } int tsnif_list(struct tsnif_handle *h) { struct trans_msg msg; TSNIF_DEBUG(INTF, "sending list command\n"); memset(&msg, 0x0, sizeof(msg)); msg.cmd = TSNIF_CMD_TTY_LIST; return trans_send(&h->trans, &msg); } int tsnif_enum(struct tsnif_handle *h, cb_tsnif_enum_t cb) { struct tsnif_term *term, *t; int err = 0; list_for_each_entry_safe(term, t, &h->terms, list) { err = cb(term); if (err) break; } return err;; }