📄 ircomm_tty_attach.c
字号:
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); self->client = FALSE; self->max_data_size = max_data_size; self->max_header_size = max_header_size; self->flow = FLOW_START; clen = skb->data[0]; if (clen) irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len, clen), &ircomm_param_info); ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL); dev_kfree_skb(skb);}/* * Function ircomm_tty_link_established (self) * * Called when the IrCOMM link is established * */void ircomm_tty_link_established(struct ircomm_tty_cb *self){ IRDA_DEBUG(2, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); if (!self->tty) return; del_timer(&self->watchdog_timer); /* * IrCOMM link is now up, and if we are not using hardware * flow-control, then declare the hardware as running. Otherwise we * will have to wait for the peer device (DCE) to raise the CTS * line. */ if (self->flags & ASYNC_CTS_FLOW) { IRDA_DEBUG(0, __FUNCTION__ "(), waiting for CTS ...\n"); return; } else { IRDA_DEBUG(2, __FUNCTION__ "(), starting hardware!\n"); self->tty->hw_stopped = 0; /* Wake up processes blocked on open */ wake_up_interruptible(&self->open_wait); } queue_task(&self->tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH);}/* * Function irlan_start_watchdog_timer (self, timeout) * * Start the watchdog timer. This timer is used to make sure that any * connection attempt is successful, and if not, we will retry after * the timeout */void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, int timeout){ ASSERT(self != NULL, return;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); irda_start_timer(&self->watchdog_timer, timeout, (void *) self, ircomm_tty_watchdog_timer_expired);}/* * Function ircomm_tty_watchdog_timer_expired (data) * * Called when the connect procedure have taken to much time. * */void ircomm_tty_watchdog_timer_expired(void *data){ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data; IRDA_DEBUG(2, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); ircomm_tty_do_event(self, IRCOMM_TTY_WD_TIMER_EXPIRED, NULL, NULL);}/* * Function ircomm_tty_state_idle (self, event, skb, info) * * Just hanging around * */static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, struct sk_buff *skb, struct ircomm_tty_info *info){ int ret = 0; IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n", ircomm_tty_state[self->state], ircomm_tty_event[event]); switch (event) { case IRCOMM_TTY_ATTACH_CABLE: /* Try to discover any remote devices */ ircomm_tty_start_watchdog_timer(self, 3*HZ); ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS); break; case IRCOMM_TTY_DISCOVERY_INDICATION: self->daddr = info->daddr; self->saddr = info->saddr; if (self->iriap) { WARNING(__FUNCTION__ "(), busy with a previous query\n"); return -EBUSY; } self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, ircomm_tty_getvalue_confirm); iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr, "IrDA:IrCOMM", "Parameters"); ircomm_tty_start_watchdog_timer(self, 3*HZ); ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS); break; case IRCOMM_TTY_CONNECT_INDICATION: del_timer(&self->watchdog_timer); /* Accept connection */ ircomm_connect_response(self->ircomm, NULL); ircomm_tty_next_state(self, IRCOMM_TTY_READY); break; case IRCOMM_TTY_WD_TIMER_EXPIRED: /* Just stay idle */ break; case IRCOMM_TTY_DETACH_CABLE: ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); break; default: IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n", ircomm_tty_event[event]); return -EINVAL; } return ret;}/* * Function ircomm_tty_state_search (self, event, skb, info) * * Trying to discover an IrCOMM device * */static int ircomm_tty_state_search(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, struct sk_buff *skb, struct ircomm_tty_info *info){ int ret = 0; IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n", ircomm_tty_state[self->state], ircomm_tty_event[event]); switch (event) { case IRCOMM_TTY_DISCOVERY_INDICATION: self->daddr = info->daddr; self->saddr = info->saddr; if (self->iriap) { WARNING(__FUNCTION__ "(), busy with a previous query\n"); return -EBUSY; } self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, ircomm_tty_getvalue_confirm); if (self->service_type == IRCOMM_3_WIRE_RAW) { iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr, "IrLPT", "IrDA:IrLMP:LsapSel"); ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL); } else { iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr, "IrDA:IrCOMM", "Parameters"); ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS); } ircomm_tty_start_watchdog_timer(self, 3*HZ); break; case IRCOMM_TTY_CONNECT_INDICATION: del_timer(&self->watchdog_timer); /* Accept connection */ ircomm_connect_response(self->ircomm, NULL); ircomm_tty_next_state(self, IRCOMM_TTY_READY); break; case IRCOMM_TTY_WD_TIMER_EXPIRED:#if 1 /* Give up */#else /* Try to discover any remote devices */ ircomm_tty_start_watchdog_timer(self, 3*HZ); irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);#endif break; case IRCOMM_TTY_DETACH_CABLE: ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); break; default: IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n", ircomm_tty_event[event]); return -EINVAL; } return ret;}/* * Function ircomm_tty_state_query (self, event, skb, info) * * Querying the remote LM-IAS for IrCOMM parameters * */static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, struct sk_buff *skb, struct ircomm_tty_info *info){ int ret = 0; IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n", ircomm_tty_state[self->state], ircomm_tty_event[event]); switch (event) { case IRCOMM_TTY_GOT_PARAMETERS: if (self->iriap) { WARNING(__FUNCTION__ "(), busy with a previous query\n"); return -EBUSY; } self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, ircomm_tty_getvalue_confirm); iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr, "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel"); ircomm_tty_start_watchdog_timer(self, 3*HZ); ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL); break; case IRCOMM_TTY_WD_TIMER_EXPIRED: /* Go back to search mode */ ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); ircomm_tty_start_watchdog_timer(self, 3*HZ); break; case IRCOMM_TTY_CONNECT_INDICATION: del_timer(&self->watchdog_timer); /* Accept connection */ ircomm_connect_response(self->ircomm, NULL); ircomm_tty_next_state(self, IRCOMM_TTY_READY); break; case IRCOMM_TTY_DETACH_CABLE: ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); break; default: IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n", ircomm_tty_event[event]); return -EINVAL; } return ret;}/* * Function ircomm_tty_state_query_lsap_sel (self, event, skb, info) * * Query remote LM-IAS for the LSAP selector which we can connect to * */static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, struct sk_buff *skb, struct ircomm_tty_info *info){ int ret = 0; IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n", ircomm_tty_state[self->state], ircomm_tty_event[event]); switch (event) { case IRCOMM_TTY_GOT_LSAPSEL: /* Connect to remote device */ ret = ircomm_connect_request(self->ircomm, self->dlsap_sel, self->saddr, self->daddr, NULL, self->service_type); ircomm_tty_start_watchdog_timer(self, 3*HZ); ircomm_tty_next_state(self, IRCOMM_TTY_SETUP); break; case IRCOMM_TTY_WD_TIMER_EXPIRED: /* Go back to search mode */ ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); ircomm_tty_start_watchdog_timer(self, 3*HZ); break; case IRCOMM_TTY_CONNECT_INDICATION: del_timer(&self->watchdog_timer); /* Accept connection */ ircomm_connect_response(self->ircomm, NULL); ircomm_tty_next_state(self, IRCOMM_TTY_READY); break; case IRCOMM_TTY_DETACH_CABLE: ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); break; default: IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n", ircomm_tty_event[event]); return -EINVAL; } return ret;}/* * Function ircomm_tty_state_setup (self, event, skb, info) * * Trying to connect * */static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, struct sk_buff *skb, struct ircomm_tty_info *info){ int ret = 0; IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n", ircomm_tty_state[self->state], ircomm_tty_event[event]); switch (event) { case IRCOMM_TTY_CONNECT_CONFIRM: del_timer(&self->watchdog_timer); ircomm_tty_next_state(self, IRCOMM_TTY_READY); /* * Send initial parameters. This will also send out queued * parameters waiting for the connection to come up */ ircomm_tty_send_initial_parameters(self); ircomm_tty_link_established(self); break; case IRCOMM_TTY_CONNECT_INDICATION: del_timer(&self->watchdog_timer); /* Accept connection */ ircomm_connect_response(self->ircomm, NULL); ircomm_tty_next_state(self, IRCOMM_TTY_READY); break; case IRCOMM_TTY_WD_TIMER_EXPIRED: /* Go back to search mode */ ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); ircomm_tty_start_watchdog_timer(self, 3*HZ); break; case IRCOMM_TTY_DETACH_CABLE: /* ircomm_disconnect_request(self->ircomm, NULL); */ ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); break; default: IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n", ircomm_tty_event[event]); return -EINVAL; } return ret;}/* * Function ircomm_tty_state_ready (self, event, skb, info) * * IrCOMM is now connected * */static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, struct sk_buff *skb, struct ircomm_tty_info *info){ int ret = 0; switch (event) { case IRCOMM_TTY_DATA_REQUEST: ret = ircomm_data_request(self->ircomm, skb); break; case IRCOMM_TTY_DETACH_CABLE: ircomm_disconnect_request(self->ircomm, NULL); ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); break; case IRCOMM_TTY_DISCONNECT_INDICATION: ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); ircomm_tty_start_watchdog_timer(self, 3*HZ); if (self->flags & ASYNC_CHECK_CD) { /* Drop carrier */ self->settings.dce = IRCOMM_DELTA_CD; ircomm_tty_check_modem_status(self); } else { IRDA_DEBUG(0, __FUNCTION__ "(), hanging up!\n"); if (self->tty) tty_hangup(self->tty); } break; default: IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n", ircomm_tty_event[event]); return -EINVAL; } return ret;}/* * Function ircomm_tty_do_event (self, event, skb) * * Process event * */int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, struct sk_buff *skb, struct ircomm_tty_info *info) { ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); IRDA_DEBUG(2, __FUNCTION__": state=%s, event=%s\n", ircomm_tty_state[self->state], ircomm_tty_event[event]); return (*state[self->state])(self, event, skb, info);}/* * Function ircomm_tty_next_state (self, state) * * Switch state * */void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state){ ASSERT(self != NULL, return;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); self->state = state; IRDA_DEBUG(2, __FUNCTION__": next state=%s, service type=%d\n", ircomm_tty_state[self->state], self->service_type);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -