📄 irlap.c
字号:
}/** Function irlap_data_indication (self, skb)** Received data frames from IR-port, so we just pass them up to* IrLMP for further processing**/void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb, int unreliable){ /* Hide LAP header from IrLMP layer */ IRDA_DEBUG(3, "%s()\n", __FUNCTION__); skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER); irlmp_link_data_indication(self->notify.instance, skb, unreliable);}/** Function irlap_data_request (self, skb)** Queue data for transmission, must wait until XMIT state**/void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb, int unreliable){ int i=0; IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == LAP_MAGIC, return;); IRDA_DEBUG(1, "%s()\n", __FUNCTION__); IRDA_DEBUG(1, "%s()\n", __FUNCTION__); skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER); /* * Must set frame format now so that the rest of the code knows * if its dealing with an I or an UI frame */ if (unreliable) skb->data[1] = UI_FRAME; else skb->data[1] = I_FRAME; /* Don't forget to refcount it - see irlmp_connect_request(). */ skb_get(skb); /* Add at the end of the queue (keep ordering) - Jean II */ skb_queue_tail(&self->txq, skb); /* * Send event if this frame only if we are in the right state * FIXME: udata should be sent first! (skb_queue_head?) */ if ((self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) { /* If we are not already processing the Tx queue, trigger * transmission immediately - Jean II */ IRDA_DEBUG(4, "first %s()\n", __FUNCTION__); if((skb_queue_len(&self->txq) <= 1) && (!self->local_busy)) { IRDA_DEBUG(4, "send %s()\n", __FUNCTION__); irlap_do_event(self, DATA_REQUEST, skb, NULL); } /* Otherwise, the packets will be sent normally at the * next pf-poll - Jean II */ }}/** Function irlap_disconnect_request (void)** Request to disconnect connection by service user*/void irlap_disconnect_request(struct irlap_cb *self){ IRDA_DEBUG(3, "%s(),%d,nrms = %d\n", __FUNCTION__,self->state,LAP_NRM_S); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == LAP_MAGIC, return;); /* Don't disconnect until all data frames are successfully sent */ if (!skb_queue_empty(&self->txq)) { 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, "%s(), disconnect pending!\n", __FUNCTION__); self->disconnect_pending = TRUE; break; }}extern int sendover_flag ;extern int rec_over_flag;/** Function irlap_disconnect_indication (void)** Disconnect request from other device**/void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason){ IRDA_DEBUG(1, "%s(), reason=%s\n", __FUNCTION__, lap_reasons[reason]); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == LAP_MAGIC, return;); /* Flush queues */ irlap_flush_all_queues(self); switch (reason) { case LAP_RESET_INDICATION: IRDA_DEBUG(1, "%s(), Sending reset request!\n", __FUNCTION__); 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: IRDA_ERROR("%s: Unknown reason %d\n", __FUNCTION__, reason); } rec_over_flag = 1; sendover_flag = 1;}/** 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; IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == LAP_MAGIC, return;); IRDA_ASSERT(discovery != NULL, return;); IRDA_DEBUG(1, "%s(), nslots = %d\n", __FUNCTION__, discovery->nslots); IRDA_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, "%s(), discovery only possible in NDM mode\n", __FUNCTION__); irlap_discovery_confirm(self, NULL); /* Note : in theory, if we are not in NDM, we could postpone * the discovery like we do for connection request. * In practice, it's not worth it. If the media was busy, * it's likely next time around it won't be busy. If we are * in REPLY state, we will get passive discovery info & event. * Jean II */ return; } /* Check if last discovery request finished in time, or if * it was aborted due to the media busy flag. */ if (self->discovery_log != NULL) { hashbin_delete(self->discovery_log, (FREE_FUNC) free); self->discovery_log = NULL; } /* All operations will occur at predictable time, no need to lock */ self->discovery_log = hashbin_new(HB_NOLOCK); if (self->discovery_log == NULL) { IRDA_WARNING("%s(), Unable to allocate discovery log!\n", __FUNCTION__); return; } info.S = discovery->nslots; /* Number of slots */ info.s = 0; /* Current slot */ self->discovery_cmd = discovery; info.discovery = discovery; /* sysctl_slot_timeout bounds are checked in irsysctl.c - Jean II */ 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){ IRDA_DEBUG(1, "%s() addr %x\n", __FUNCTION__,self); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == LAP_MAGIC, return;); IRDA_ASSERT(self->notify.instance != NULL, return;); /* * Check for successful discovery, since we are then allowed to clear * the media busy condition (IrLAP 6.13.4 - p.94). This should allow * us to make connection attempts much faster and easier (i.e. no * collisions). * Setting media busy to false will also generate an event allowing * to process pending events in NDM state machine. * Note : the spec doesn't define what's a successful discovery is. * If we want Ultra to work, it's successful even if there is * nobody discovered - Jean II */ if (discovery_log) 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(1, "%s()\n", __FUNCTION__); IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == LAP_MAGIC, return;); IRDA_ASSERT(discovery != NULL, return;); IRDA_ASSERT(self->notify.instance != NULL, return;); /* A device is very likely to connect immediately after it performs * a successful discovery. This means that in our case, we are much * more likely to receive a connection request over the medium. * So, we backoff to avoid collisions. * IrLAP spec 6.13.4 suggest 100ms... * Note : this little trick actually make a *BIG* difference. If I set * my Linux box with discovery enabled and one Ultra frame sent every * second, my Palm has no trouble connecting to it every time ! * Jean II */ irda_device_set_media_busy(self->netdev, SMALL); 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: IRDA_MESSAGE("IrLAP, no activity on link!\n"); break; case STATUS_NOISY: IRDA_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, "%s()\n", __FUNCTION__); IRDA_ASSERT(self != NULL, return;); IRDA_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, "%s()\n", __FUNCTION__);}/** 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; IRDA_ASSERT((S - s) > 0, return 0;); // modify by xugan time_t i_time = kern_time_get(); rand += i_time; rand ^= (rand << 12); rand ^= (rand >> 20); slot = s + rand % (S-s); IRDA_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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -