📄 irlap.c
字号:
#ifdef CONFIG_IRDA_ULTRAvoid irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb){ IRDA_DEBUG(1, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == LAP_MAGIC, return;); ASSERT(skb != NULL, return;); /* Hide LAP header from IrLMP layer */ skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER); skb_get(skb); /*LEVEL4*/ irlmp_link_unitdata_indication(self->notify.instance, skb);}#endif /* CONFIG_IRDA_ULTRA *//* * Function irlap_disconnect_request (void) * * Request to disconnect connection by service user */void irlap_disconnect_request(struct irlap_cb *self) { IRDA_DEBUG(3, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == LAP_MAGIC, return;); /* Don't disconnect until all data frames are successfully sent */ if (skb_queue_len(&self->txq) > 0) { self->disconnect_pending = TRUE; return; } /* Check if we are in the right state for disconnecting */ switch (self->state) { case LAP_XMIT_P: /* FALLTROUGH */ case LAP_XMIT_S: /* FALLTROUGH */ case LAP_CONN: /* FALLTROUGH */ case LAP_RESET_WAIT: /* FALLTROUGH */ case LAP_RESET_CHECK: irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL); break; default: IRDA_DEBUG(2, __FUNCTION__ "(), disconnect pending!\n"); self->disconnect_pending = TRUE; break; }}/* * Function irlap_disconnect_indication (void) * * Disconnect request from other device * */void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason) { IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); ASSERT(self != NULL, return;); ASSERT(self->magic == LAP_MAGIC, return;);#ifdef CONFIG_IRDA_COMPRESSION irda_free_compression(self);#endif /* Flush queues */ irlap_flush_all_queues(self); switch (reason) { case LAP_RESET_INDICATION: IRDA_DEBUG(1, __FUNCTION__ "(), Sending reset request!\n"); irlap_do_event(self, RESET_REQUEST, NULL, NULL); break; case LAP_NO_RESPONSE: /* FALLTROUGH */ case LAP_DISC_INDICATION: /* FALLTROUGH */ case LAP_FOUND_NONE: /* FALLTROUGH */ case LAP_MEDIA_BUSY: irlmp_link_disconnect_indication(self->notify.instance, self, reason, NULL); break; default: ERROR(__FUNCTION__ "(), Unknown reason %d\n", reason); }}/* * Function irlap_discovery_request (gen_addr_bit) * * Start one single discovery operation. * */void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery) { struct irlap_info info; ASSERT(self != NULL, return;); ASSERT(self->magic == LAP_MAGIC, return;); ASSERT(discovery != NULL, return;); IRDA_DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots); ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) || (discovery->nslots == 8) || (discovery->nslots == 16), return;); /* Discovery is only possible in NDM mode */ if (self->state != LAP_NDM) { IRDA_DEBUG(4, __FUNCTION__ "(), discovery only possible in NDM mode\n"); irlap_discovery_confirm(self, NULL); return; } /* Check if last discovery request finished in time */ if (self->discovery_log != NULL) { hashbin_delete(self->discovery_log, (FREE_FUNC) kfree); self->discovery_log = NULL; } self->discovery_log= hashbin_new(HB_LOCAL); info.S = discovery->nslots; /* Number of slots */ info.s = 0; /* Current slot */ self->discovery_cmd = discovery; info.discovery = discovery; /* Check if the slot timeout is within limits */ if (sysctl_slot_timeout < 20) { ERROR(__FUNCTION__ "(), to low value for slot timeout!\n"); sysctl_slot_timeout = 20; } /* * Highest value is actually 8, but we allow higher since * some devices seems to require it. */ if (sysctl_slot_timeout > 160) { ERROR(__FUNCTION__ "(), to high value for slot timeout!\n"); sysctl_slot_timeout = 160; } self->slot_timeout = sysctl_slot_timeout * HZ / 1000; irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);}/* * Function irlap_discovery_confirm (log) * * A device has been discovered in front of this station, we * report directly to LMP. */void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log) { ASSERT(self != NULL, return;); ASSERT(self->magic == LAP_MAGIC, return;); ASSERT(self->notify.instance != NULL, return;); /* * Check for successful discovery, since we are then allowed to clear * the media busy condition (irlap p.94). This should allow us to make * connection attempts much easier. */ if (discovery_log && HASHBIN_GET_SIZE(discovery_log) > 0) irda_device_set_media_busy(self->netdev, FALSE); /* Inform IrLMP */ irlmp_link_discovery_confirm(self->notify.instance, discovery_log);}/* * Function irlap_discovery_indication (log) * * Somebody is trying to discover us! * */void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery) { IRDA_DEBUG(4, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == LAP_MAGIC, return;); ASSERT(discovery != NULL, return;); ASSERT(self->notify.instance != NULL, return;); irlmp_link_discovery_indication(self->notify.instance, discovery);}/* * Function irlap_status_indication (quality_of_link) * * * */void irlap_status_indication(struct irlap_cb *self, int quality_of_link) { switch (quality_of_link) { case STATUS_NO_ACTIVITY: MESSAGE("IrLAP, no activity on link!\n"); break; case STATUS_NOISY: MESSAGE("IrLAP, noisy link!\n"); break; default: break; } irlmp_status_indication(self->notify.instance, quality_of_link, LOCK_NO_CHANGE);}/* * Function irlap_reset_indication (void) * * * */void irlap_reset_indication(struct irlap_cb *self){ IRDA_DEBUG(1, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == LAP_MAGIC, return;); if (self->state == LAP_RESET_WAIT) irlap_do_event(self, RESET_REQUEST, NULL, NULL); else irlap_do_event(self, RESET_RESPONSE, NULL, NULL);}/* * Function irlap_reset_confirm (void) * * * */void irlap_reset_confirm(void){ IRDA_DEBUG(1, __FUNCTION__ "()\n");}/* * Function irlap_generate_rand_time_slot (S, s) * * Generate a random time slot between s and S-1 where * S = Number of slots (0 -> S-1) * s = Current slot */int irlap_generate_rand_time_slot(int S, int s) { static int rand; int slot; ASSERT((S - s) > 0, return 0;); rand += jiffies; rand ^= (rand << 12); rand ^= (rand >> 20); slot = s + rand % (S-s); ASSERT((slot >= s) || (slot < S), return 0;); return slot;}/* * Function irlap_update_nr_received (nr) * * Remove all acknowledged frames in current window queue. This code is * not intuitive and you should not try to change it. If you think it * contains bugs, please mail a patch to the author instead. */void irlap_update_nr_received(struct irlap_cb *self, int nr) { struct sk_buff *skb = NULL; int count = 0; /* * Remove all the ack-ed frames from the window queue. */ /* * Optimize for the common case. It is most likely that the receiver * will acknowledge all the frames we have sent! So in that case we * delete all frames stored in window. */ if (nr == self->vs) { while ((skb = skb_dequeue(&self->wx_list)) != NULL) { dev_kfree_skb(skb); } /* The last acked frame is the next to send minus one */ self->va = nr - 1; } else { /* Remove all acknowledged frames in current window */ while ((skb_peek(&self->wx_list) != NULL) && (((self->va+1) % 8) != nr)) { skb = skb_dequeue(&self->wx_list); dev_kfree_skb(skb); self->va = (self->va + 1) % 8; count++; } } /* Advance window */ self->window = self->window_size - skb_queue_len(&self->wx_list);}/* * Function irlap_validate_ns_received (ns) * * Validate the next to send (ns) field from received frame. */int irlap_validate_ns_received(struct irlap_cb *self, int ns) { /* ns as expected? */ if (ns == self->vr) return NS_EXPECTED; /* * Stations are allowed to treat invalid NS as unexpected NS * IrLAP, Recv ... with-invalid-Ns. p. 84 */ return NS_UNEXPECTED; /* return NR_INVALID; */}/* * Function irlap_validate_nr_received (nr) * * Validate the next to receive (nr) field from received frame. * */int irlap_validate_nr_received(struct irlap_cb *self, int nr) { /* nr as expected? */ if (nr == self->vs) { IRDA_DEBUG(4, __FUNCTION__ "(), expected!\n"); return NR_EXPECTED; } /* * unexpected nr? (but within current window), first we check if the * ns numbers of the frames in the current window wrap. */ if (self->va < self->vs) { if ((nr >= self->va) && (nr <= self->vs)) return NR_UNEXPECTED; } else { if ((nr >= self->va) || (nr <= self->vs)) return NR_UNEXPECTED; } /* Invalid nr! */ return NR_INVALID;}/* * Function irlap_initiate_connection_state () * * Initialize the connection state parameters * */void irlap_initiate_connection_state(struct irlap_cb *self) { IRDA_DEBUG(4, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == LAP_MAGIC, return;); /* Next to send and next to receive */ self->vs = self->vr = 0; /* Last frame which got acked (0 - 1) % 8 */ self->va = 7; self->window = 1; self->remote_busy = FALSE; self->retry_count = 0;}/* * Function irlap_wait_min_turn_around (self, qos) * * Wait negotiated minimum turn around time, this function actually sets * the number of BOS's that must be sent before the next transmitted * frame in order to delay for the specified amount of time. This is * done to avoid using timers, and the forbidden udelay! */void irlap_wait_min_turn_around(struct irlap_cb *self, struct qos_info *qos) { __u32 min_turn_time; __u32 speed; /* Get QoS values. */ speed = qos->baud_rate.value; min_turn_time = qos->min_turn_time.value; /* No need to calculate XBOFs for speeds over 115200 bps */ if (speed > 115200) { self->mtt_required = min_turn_time; return; } /* * Send additional BOF's for the next frame for the requested * min turn time, so now we must calculate how many chars (XBOF's) we * must send for the requested time period (min turn time) */ self->xbofs_delay = irlap_min_turn_time_in_bytes(speed, min_turn_time);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -