irlap.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:32k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*********************************************************************
  2.  *                
  3.  * Filename:      irlap.c
  4.  * Version:       1.0
  5.  * Description:   IrLAP implementation for Linux
  6.  * Status:        Stable
  7.  * Author:        Dag Brattli <dagb@cs.uit.no>
  8.  * Created at:    Mon Aug  4 20:40:53 1997
  9.  * Modified at:   Tue Dec 14 09:26:44 1999
  10.  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  11.  * 
  12.  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  13.  *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
  14.  *     
  15.  *     This program is free software; you can redistribute it and/or 
  16.  *     modify it under the terms of the GNU General Public License as 
  17.  *     published by the Free Software Foundation; either version 2 of 
  18.  *     the License, or (at your option) any later version.
  19.  * 
  20.  *     This program is distributed in the hope that it will be useful,
  21.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23.  *     GNU General Public License for more details.
  24.  * 
  25.  *     You should have received a copy of the GNU General Public License 
  26.  *     along with this program; if not, write to the Free Software 
  27.  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
  28.  *     MA 02111-1307 USA
  29.  *     
  30.  ********************************************************************/
  31. #include <linux/config.h>
  32. #include <linux/slab.h>
  33. #include <linux/string.h>
  34. #include <linux/skbuff.h>
  35. #include <linux/delay.h>
  36. #include <linux/proc_fs.h>
  37. #include <linux/init.h>
  38. #include <linux/random.h>
  39. #include <net/irda/irda.h>
  40. #include <net/irda/irda_device.h>
  41. #include <net/irda/irqueue.h>
  42. #include <net/irda/irlmp.h>
  43. #include <net/irda/irlmp_frame.h>
  44. #include <net/irda/irlap_frame.h>
  45. #include <net/irda/irlap.h>
  46. #include <net/irda/timer.h>
  47. #include <net/irda/qos.h>
  48. hashbin_t *irlap = NULL;
  49. int sysctl_slot_timeout = SLOT_TIMEOUT * 1000 / HZ;
  50. /* This is the delay of missed pf period before generating an event
  51.  * to the application. The spec mandate 3 seconds, but in some cases
  52.  * it's way too long. - Jean II */
  53. int sysctl_warn_noreply_time = 3;
  54. extern void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb);
  55. static void __irlap_close(struct irlap_cb *self);
  56. #ifdef CONFIG_IRDA_DEBUG
  57. static char *lap_reasons[] = {
  58. "ERROR, NOT USED",
  59. "LAP_DISC_INDICATION",
  60. "LAP_NO_RESPONSE",
  61. "LAP_RESET_INDICATION",
  62. "LAP_FOUND_NONE",
  63. "LAP_MEDIA_BUSY",
  64. "LAP_PRIMARY_CONFLICT",
  65. "ERROR, NOT USED",
  66. };
  67. #endif /* CONFIG_IRDA_DEBUG */
  68. #ifdef CONFIG_PROC_FS
  69. int irlap_proc_read(char *, char **, off_t, int);
  70. #endif /* CONFIG_PROC_FS */
  71. int __init irlap_init(void)
  72. {
  73. /* Allocate master array */
  74. irlap = hashbin_new(HB_LOCAL);
  75. if (irlap == NULL) {
  76.         ERROR(__FUNCTION__ "(), can't allocate irlap hashbin!n");
  77. return -ENOMEM;
  78. }
  79. return 0;
  80. }
  81. void irlap_cleanup(void)
  82. {
  83. ASSERT(irlap != NULL, return;);
  84. hashbin_delete(irlap, (FREE_FUNC) __irlap_close);
  85. }
  86. /*
  87.  * Function irlap_open (driver)
  88.  *
  89.  *    Initialize IrLAP layer
  90.  *
  91.  */
  92. struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos,
  93.     char * hw_name)
  94. {
  95. struct irlap_cb *self;
  96. IRDA_DEBUG(4, __FUNCTION__ "()n");
  97. /* Initialize the irlap structure. */
  98. self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);
  99. if (self == NULL)
  100. return NULL;
  101. memset(self, 0, sizeof(struct irlap_cb));
  102. self->magic = LAP_MAGIC;
  103. /* Make a binding between the layers */
  104. self->netdev = dev;
  105. self->qos_dev = qos;
  106. /* Copy hardware name */
  107. if(hw_name != NULL) {
  108. strncpy(self->hw_name, hw_name, 2*IFNAMSIZ);
  109. self->hw_name[2*IFNAMSIZ] = '';
  110. } else {
  111. self->hw_name[0] = '';
  112. }
  113. /* FIXME: should we get our own field? */
  114. dev->atalk_ptr = self;
  115. irlap_next_state(self, LAP_OFFLINE);
  116. /* Initialize transmit queue */
  117. skb_queue_head_init(&self->txq);
  118. skb_queue_head_init(&self->txq_ultra);
  119. skb_queue_head_init(&self->wx_list);
  120. /* My unique IrLAP device address! */
  121. get_random_bytes(&self->saddr, sizeof(self->saddr));
  122. memcpy(dev->dev_addr, &self->saddr, 4);
  123. init_timer(&self->slot_timer);
  124. init_timer(&self->query_timer);
  125. init_timer(&self->discovery_timer);
  126. init_timer(&self->final_timer);
  127. init_timer(&self->poll_timer);
  128. init_timer(&self->wd_timer);
  129. init_timer(&self->backoff_timer);
  130. init_timer(&self->media_busy_timer);
  131. irlap_apply_default_connection_parameters(self);
  132. self->N3 = 3; /* # connections attemts to try before giving up */
  133. irlap_next_state(self, LAP_NDM);
  134. hashbin_insert(irlap, (irda_queue_t *) self, self->saddr, NULL);
  135. irlmp_register_link(self, self->saddr, &self->notify);
  136. return self;
  137. }
  138. /*
  139.  * Function __irlap_close (self)
  140.  *
  141.  *    Remove IrLAP and all allocated memory. Stop any pending timers.
  142.  *
  143.  */
  144. static void __irlap_close(struct irlap_cb *self)
  145. {
  146. ASSERT(self != NULL, return;);
  147. ASSERT(self->magic == LAP_MAGIC, return;);
  148. /* Stop timers */
  149. del_timer(&self->slot_timer);
  150. del_timer(&self->query_timer);
  151. del_timer(&self->discovery_timer);
  152. del_timer(&self->final_timer);
  153. del_timer(&self->poll_timer);
  154. del_timer(&self->wd_timer);
  155. del_timer(&self->backoff_timer);
  156. del_timer(&self->media_busy_timer);
  157. irlap_flush_all_queues(self);
  158.        
  159. self->magic = 0;
  160. kfree(self);
  161. }
  162. /*
  163.  * Function irlap_close (self)
  164.  *
  165.  *    Remove IrLAP instance
  166.  *
  167.  */
  168. void irlap_close(struct irlap_cb *self) 
  169. {
  170. struct irlap_cb *lap;
  171. IRDA_DEBUG(4, __FUNCTION__ "()n");
  172. ASSERT(self != NULL, return;);
  173. ASSERT(self->magic == LAP_MAGIC, return;);
  174. irlap_disconnect_indication(self, LAP_DISC_INDICATION);
  175. irlmp_unregister_link(self->saddr);
  176. self->notify.instance = NULL;
  177. /* Be sure that we manage to remove ourself from the hash */
  178. lap = hashbin_remove(irlap, self->saddr, NULL);
  179. if (!lap) {
  180. IRDA_DEBUG(1, __FUNCTION__ "(), Didn't find myself!n");
  181. return;
  182. }
  183. __irlap_close(lap);
  184. }
  185. /*
  186.  * Function irlap_connect_indication (self, skb)
  187.  *
  188.  *    Another device is attempting to make a connection
  189.  *
  190.  */
  191. void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb) 
  192. {
  193. IRDA_DEBUG(4, __FUNCTION__ "()n");
  194. ASSERT(self != NULL, return;);
  195. ASSERT(self->magic == LAP_MAGIC, return;);
  196. irlap_init_qos_capabilities(self, NULL); /* No user QoS! */
  197. skb_get(skb); /*LEVEL4*/
  198. irlmp_link_connect_indication(self->notify.instance, self->saddr, 
  199.       self->daddr, &self->qos_tx, skb);
  200. }
  201. /*
  202.  * Function irlap_connect_response (self, skb)
  203.  *
  204.  *    Service user has accepted incoming connection
  205.  *
  206.  */
  207. void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb) 
  208. {
  209. IRDA_DEBUG(4, __FUNCTION__ "()n");
  210. irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);
  211. kfree_skb(skb);
  212. }
  213. /*
  214.  * Function irlap_connect_request (self, daddr, qos_user, sniff)
  215.  *
  216.  *    Request connection with another device, sniffing is not implemented 
  217.  *    yet.
  218.  *
  219.  */
  220. void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 
  221.    struct qos_info *qos_user, int sniff) 
  222. {
  223. IRDA_DEBUG(3, __FUNCTION__ "(), daddr=0x%08xn", daddr);
  224. ASSERT(self != NULL, return;);
  225. ASSERT(self->magic == LAP_MAGIC, return;);
  226.   self->daddr = daddr;
  227. /*
  228.  *  If the service user specifies QoS values for this connection, 
  229.  *  then use them
  230.  */
  231. irlap_init_qos_capabilities(self, qos_user);
  232. if ((self->state == LAP_NDM) && !self->media_busy)
  233. irlap_do_event(self, CONNECT_REQUEST, NULL, NULL);
  234. else
  235. self->connect_pending = TRUE;
  236. }
  237. /*
  238.  * Function irlap_connect_confirm (self, skb)
  239.  *
  240.  *    Connection request has been accepted
  241.  *
  242.  */
  243. void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
  244. {
  245. IRDA_DEBUG(4, __FUNCTION__ "()n");
  246. ASSERT(self != NULL, return;);
  247. ASSERT(self->magic == LAP_MAGIC, return;);
  248. skb_get(skb); /*LEVEL4*/
  249. irlmp_link_connect_confirm(self->notify.instance, &self->qos_tx, skb);
  250. }
  251. /*
  252.  * Function irlap_data_indication (self, skb)
  253.  *
  254.  *    Received data frames from IR-port, so we just pass them up to 
  255.  *    IrLMP for further processing
  256.  *
  257.  */
  258. void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb,
  259.    int unreliable) 
  260. {
  261. /* Hide LAP header from IrLMP layer */
  262. skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
  263. skb_get(skb); /*LEVEL4*/
  264. irlmp_link_data_indication(self->notify.instance, skb, unreliable);
  265. }
  266. /*
  267.  * Function irlap_data_request (self, skb)
  268.  *
  269.  *    Queue data for transmission, must wait until XMIT state
  270.  *
  271.  */
  272. void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb, 
  273. int unreliable)
  274. {
  275. ASSERT(self != NULL, return;);
  276. ASSERT(self->magic == LAP_MAGIC, return;);
  277. IRDA_DEBUG(3, __FUNCTION__ "()n");
  278. ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
  279.        return;);
  280. skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
  281. /*  
  282.  *  Must set frame format now so that the rest of the code knows 
  283.  *  if its dealing with an I or an UI frame
  284.  */
  285. if (unreliable)
  286. skb->data[1] = UI_FRAME;
  287. else
  288. skb->data[1] = I_FRAME;
  289. /* 
  290.  *  Send event if this frame only if we are in the right state 
  291.  *  FIXME: udata should be sent first! (skb_queue_head?)
  292.  */
  293.    if ((self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) {
  294. /*
  295.  *  Check if the transmit queue contains some unsent frames,
  296.  *  and if so, make sure they are sent first
  297.  */
  298. if (!skb_queue_empty(&self->txq)) {
  299. skb_queue_tail(&self->txq, skb);
  300. skb = skb_dequeue(&self->txq);
  301. ASSERT(skb != NULL, return;);
  302. }
  303. irlap_do_event(self, SEND_I_CMD, skb, NULL);
  304. kfree_skb(skb);
  305. } else
  306. skb_queue_tail(&self->txq, skb);
  307. }
  308. /*
  309.  * Function irlap_unitdata_request (self, skb)
  310.  *
  311.  *    Send Ultra data. This is data that must be sent outside any connection
  312.  *
  313.  */
  314. #ifdef CONFIG_IRDA_ULTRA
  315. void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
  316. {
  317. ASSERT(self != NULL, return;);
  318. ASSERT(self->magic == LAP_MAGIC, return;);
  319. IRDA_DEBUG(3, __FUNCTION__ "()n");
  320. ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
  321.        return;);
  322. skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
  323. skb->data[0] = CBROADCAST;
  324. skb->data[1] = UI_FRAME;
  325. skb_queue_tail(&self->txq_ultra, skb);
  326. irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);
  327. }
  328. #endif /*CONFIG_IRDA_ULTRA */
  329. /*
  330.  * Function irlap_udata_indication (self, skb)
  331.  *
  332.  *    Receive Ultra data. This is data that is received outside any connection
  333.  *
  334.  */
  335. #ifdef CONFIG_IRDA_ULTRA
  336. void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
  337. {
  338. IRDA_DEBUG(1, __FUNCTION__ "()n"); 
  339. ASSERT(self != NULL, return;);
  340. ASSERT(self->magic == LAP_MAGIC, return;);
  341. ASSERT(skb != NULL, return;);
  342. /* Hide LAP header from IrLMP layer */
  343. skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
  344. skb_get(skb); /*LEVEL4*/
  345. irlmp_link_unitdata_indication(self->notify.instance, skb);
  346. }
  347. #endif /* CONFIG_IRDA_ULTRA */
  348. /*
  349.  * Function irlap_disconnect_request (void)
  350.  *
  351.  *    Request to disconnect connection by service user
  352.  */
  353. void irlap_disconnect_request(struct irlap_cb *self) 
  354. {
  355. IRDA_DEBUG(3, __FUNCTION__ "()n");
  356. ASSERT(self != NULL, return;);
  357. ASSERT(self->magic == LAP_MAGIC, return;);
  358. /* Don't disconnect until all data frames are successfully sent */
  359. if (skb_queue_len(&self->txq) > 0) {
  360. self->disconnect_pending = TRUE;
  361. return;
  362. }
  363. /* Check if we are in the right state for disconnecting */
  364. switch (self->state) {
  365. case LAP_XMIT_P:        /* FALLTROUGH */
  366. case LAP_XMIT_S:        /* FALLTROUGH */
  367.   case LAP_CONN:          /* FALLTROUGH */
  368.   case LAP_RESET_WAIT:    /* FALLTROUGH */
  369.   case LAP_RESET_CHECK:   
  370. irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
  371. break;
  372. default:
  373. IRDA_DEBUG(2, __FUNCTION__ "(), disconnect pending!n");
  374. self->disconnect_pending = TRUE;
  375. break;
  376. }
  377. }
  378. /*
  379.  * Function irlap_disconnect_indication (void)
  380.  *
  381.  *    Disconnect request from other device
  382.  *
  383.  */
  384. void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason) 
  385. {
  386. IRDA_DEBUG(1, __FUNCTION__ "(), reason=%sn", lap_reasons[reason]); 
  387. ASSERT(self != NULL, return;);
  388. ASSERT(self->magic == LAP_MAGIC, return;);
  389. /* Flush queues */
  390. irlap_flush_all_queues(self);
  391. switch (reason) {
  392. case LAP_RESET_INDICATION:
  393. IRDA_DEBUG(1, __FUNCTION__ "(), Sending reset request!n");
  394. irlap_do_event(self, RESET_REQUEST, NULL, NULL);
  395. break;
  396. case LAP_NO_RESPONSE:    /* FALLTROUGH */
  397. case LAP_DISC_INDICATION:  /* FALLTROUGH */
  398. case LAP_FOUND_NONE:       /* FALLTROUGH */
  399. case LAP_MEDIA_BUSY:
  400. irlmp_link_disconnect_indication(self->notify.instance, self, 
  401.  reason, NULL);
  402. break;
  403. default:
  404. ERROR(__FUNCTION__ "(), Unknown reason %dn", reason);
  405. }
  406. }
  407. /*
  408.  * Function irlap_discovery_request (gen_addr_bit)
  409.  *
  410.  *    Start one single discovery operation.
  411.  *
  412.  */
  413. void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery) 
  414. {
  415. struct irlap_info info;
  416. ASSERT(self != NULL, return;);
  417. ASSERT(self->magic == LAP_MAGIC, return;);
  418. ASSERT(discovery != NULL, return;);
  419. IRDA_DEBUG(4, __FUNCTION__ "(), nslots = %dn", discovery->nslots);
  420. ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
  421.        (discovery->nslots == 8) || (discovery->nslots == 16), 
  422.        return;);
  423.    /* Discovery is only possible in NDM mode */
  424. if (self->state != LAP_NDM) {
  425. IRDA_DEBUG(4, __FUNCTION__ 
  426.    "(), discovery only possible in NDM moden");
  427. irlap_discovery_confirm(self, NULL);
  428. /* Note : in theory, if we are not in NDM, we could postpone
  429.  * the discovery like we do for connection request.
  430.  * In practice, it's not worth it. If the media was busy,
  431.  * it's likely next time around it won't be busy. If we are
  432.  * in REPLY state, we will get passive discovery info & event.
  433.  * Jean II */
  434. return;
  435. }
  436. /* Check if last discovery request finished in time, or if
  437.  * it was aborted due to the media busy flag. */
  438. if (self->discovery_log != NULL) {
  439. hashbin_delete(self->discovery_log, (FREE_FUNC) kfree);
  440. self->discovery_log = NULL;
  441. }
  442. self->discovery_log= hashbin_new(HB_LOCAL);
  443. info.S = discovery->nslots; /* Number of slots */
  444. info.s = 0; /* Current slot */
  445. self->discovery_cmd = discovery;
  446. info.discovery = discovery;
  447. /* sysctl_slot_timeout bounds are checked in irsysctl.c - Jean II */
  448. self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
  449. irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
  450. }
  451. /*
  452.  * Function irlap_discovery_confirm (log)
  453.  *
  454.  *    A device has been discovered in front of this station, we
  455.  *    report directly to LMP.
  456.  */
  457. void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log) 
  458. {
  459. ASSERT(self != NULL, return;);
  460. ASSERT(self->magic == LAP_MAGIC, return;);
  461. ASSERT(self->notify.instance != NULL, return;);
  462. /* 
  463.  * Check for successful discovery, since we are then allowed to clear 
  464.  * the media busy condition (IrLAP 6.13.4 - p.94). This should allow
  465.  * us to make connection attempts much faster and easier (i.e. no
  466.  * collisions).
  467.  * Setting media busy to false will also generate an event allowing
  468.  * to process pending events in NDM state machine.
  469.  * Note : the spec doesn't define what's a successful discovery is.
  470.  * If we want Ultra to work, it's successful even if there is
  471.  * nobody discovered - Jean II
  472.  */
  473. if (discovery_log)
  474. irda_device_set_media_busy(self->netdev, FALSE);
  475. /* Inform IrLMP */
  476. irlmp_link_discovery_confirm(self->notify.instance, discovery_log);
  477. }
  478. /*
  479.  * Function irlap_discovery_indication (log)
  480.  *
  481.  *    Somebody is trying to discover us!
  482.  *
  483.  */
  484. void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery) 
  485. {
  486. IRDA_DEBUG(4, __FUNCTION__ "()n");
  487. ASSERT(self != NULL, return;);
  488. ASSERT(self->magic == LAP_MAGIC, return;);
  489. ASSERT(discovery != NULL, return;);
  490. ASSERT(self->notify.instance != NULL, return;);
  491. /* A device is very likely to connect immediately after it performs
  492.  * a successful discovery. This means that in our case, we are much
  493.  * more likely to receive a connection request over the medium.
  494.  * So, we backoff to avoid collisions.
  495.  * IrLAP spec 6.13.4 suggest 100ms...
  496.  * Note : this little trick actually make a *BIG* difference. If I set
  497.  * my Linux box with discovery enabled and one Ultra frame sent every
  498.  * second, my Palm has no trouble connecting to it every time !
  499.  * Jean II */
  500. irda_device_set_media_busy(self->netdev, SMALL);
  501. irlmp_link_discovery_indication(self->notify.instance, discovery);
  502. }
  503. /*
  504.  * Function irlap_status_indication (quality_of_link)
  505.  *
  506.  *    
  507.  *
  508.  */
  509. void irlap_status_indication(struct irlap_cb *self, int quality_of_link) 
  510. {
  511. switch (quality_of_link) {
  512. case STATUS_NO_ACTIVITY:
  513. MESSAGE("IrLAP, no activity on link!n");
  514. break;
  515. case STATUS_NOISY:
  516. MESSAGE("IrLAP, noisy link!n");
  517. break;
  518. default:
  519. break;
  520. }
  521. irlmp_status_indication(self->notify.instance,
  522. quality_of_link, LOCK_NO_CHANGE);
  523. }
  524. /*
  525.  * Function irlap_reset_indication (void)
  526.  *
  527.  *    
  528.  *
  529.  */
  530. void irlap_reset_indication(struct irlap_cb *self)
  531. {
  532. IRDA_DEBUG(1, __FUNCTION__ "()n");
  533. ASSERT(self != NULL, return;);
  534. ASSERT(self->magic == LAP_MAGIC, return;);
  535. if (self->state == LAP_RESET_WAIT)
  536. irlap_do_event(self, RESET_REQUEST, NULL, NULL);
  537. else
  538. irlap_do_event(self, RESET_RESPONSE, NULL, NULL);
  539. }
  540. /*
  541.  * Function irlap_reset_confirm (void)
  542.  *
  543.  *    
  544.  *
  545.  */
  546. void irlap_reset_confirm(void)
  547. {
  548.   IRDA_DEBUG(1, __FUNCTION__ "()n");
  549. }
  550. /*
  551.  * Function irlap_generate_rand_time_slot (S, s)
  552.  *
  553.  *    Generate a random time slot between s and S-1 where
  554.  *    S = Number of slots (0 -> S-1)
  555.  *    s = Current slot
  556.  */
  557. int irlap_generate_rand_time_slot(int S, int s) 
  558. {
  559. static int rand;
  560. int slot;
  561. ASSERT((S - s) > 0, return 0;);
  562. rand += jiffies;
  563. rand ^= (rand << 12);
  564. rand ^= (rand >> 20);
  565. slot = s + rand % (S-s);
  566. ASSERT((slot >= s) || (slot < S), return 0;);
  567. return slot;
  568. }
  569. /*
  570.  * Function irlap_update_nr_received (nr)
  571.  *
  572.  *    Remove all acknowledged frames in current window queue. This code is 
  573.  *    not intuitive and you should not try to change it. If you think it
  574.  *    contains bugs, please mail a patch to the author instead.
  575.  */
  576. void irlap_update_nr_received(struct irlap_cb *self, int nr) 
  577. {
  578. struct sk_buff *skb = NULL;
  579. int count = 0;
  580. /*
  581.          * Remove all the ack-ed frames from the window queue.
  582.          */
  583. /* 
  584.  *  Optimize for the common case. It is most likely that the receiver
  585.  *  will acknowledge all the frames we have sent! So in that case we
  586.  *  delete all frames stored in window.
  587.  */
  588. if (nr == self->vs) {
  589. while ((skb = skb_dequeue(&self->wx_list)) != NULL) {
  590. dev_kfree_skb(skb);
  591. }
  592. /* The last acked frame is the next to send minus one */
  593. self->va = nr - 1;
  594. } else {
  595. /* Remove all acknowledged frames in current window */
  596. while ((skb_peek(&self->wx_list) != NULL) && 
  597.        (((self->va+1) % 8) != nr)) 
  598. {
  599. skb = skb_dequeue(&self->wx_list);
  600. dev_kfree_skb(skb);
  601. self->va = (self->va + 1) % 8;
  602. count++;
  603. }
  604. }
  605. /* Advance window */
  606. self->window = self->window_size - skb_queue_len(&self->wx_list);
  607. }
  608. /*
  609.  * Function irlap_validate_ns_received (ns)
  610.  *
  611.  *    Validate the next to send (ns) field from received frame.
  612.  */
  613. int irlap_validate_ns_received(struct irlap_cb *self, int ns) 
  614. {
  615. /*  ns as expected?  */
  616. if (ns == self->vr)
  617. return NS_EXPECTED;
  618. /*
  619.  *  Stations are allowed to treat invalid NS as unexpected NS
  620.  *  IrLAP, Recv ... with-invalid-Ns. p. 84
  621.  */
  622. return NS_UNEXPECTED;
  623. /* return NR_INVALID; */
  624. }
  625. /*
  626.  * Function irlap_validate_nr_received (nr)
  627.  *
  628.  *    Validate the next to receive (nr) field from received frame.
  629.  *
  630.  */
  631. int irlap_validate_nr_received(struct irlap_cb *self, int nr) 
  632. {
  633. /*  nr as expected?  */
  634. if (nr == self->vs) {
  635. IRDA_DEBUG(4, __FUNCTION__ "(), expected!n");
  636. return NR_EXPECTED;
  637. }
  638. /*
  639.  *  unexpected nr? (but within current window), first we check if the 
  640.  *  ns numbers of the frames in the current window wrap.
  641.  */
  642. if (self->va < self->vs) {
  643. if ((nr >= self->va) && (nr <= self->vs))
  644. return NR_UNEXPECTED;
  645. } else {
  646. if ((nr >= self->va) || (nr <= self->vs)) 
  647. return NR_UNEXPECTED;
  648. }
  649. /* Invalid nr!  */
  650. return NR_INVALID;
  651. }
  652. /*
  653.  * Function irlap_initiate_connection_state ()
  654.  *
  655.  *    Initialize the connection state parameters
  656.  *
  657.  */
  658. void irlap_initiate_connection_state(struct irlap_cb *self) 
  659. {
  660. IRDA_DEBUG(4, __FUNCTION__ "()n");
  661. ASSERT(self != NULL, return;);
  662. ASSERT(self->magic == LAP_MAGIC, return;);
  663. /* Next to send and next to receive */
  664. self->vs = self->vr = 0;
  665. /* Last frame which got acked (0 - 1) % 8 */
  666. self->va = 7;
  667. self->window = 1;
  668. self->remote_busy = FALSE;
  669. self->retry_count = 0;
  670. }
  671. /*
  672.  * Function irlap_wait_min_turn_around (self, qos)
  673.  *
  674.  *    Wait negotiated minimum turn around time, this function actually sets
  675.  *    the number of BOS's that must be sent before the next transmitted
  676.  *    frame in order to delay for the specified amount of time. This is
  677.  *    done to avoid using timers, and the forbidden udelay!
  678.  */
  679. void irlap_wait_min_turn_around(struct irlap_cb *self, struct qos_info *qos) 
  680. {
  681. __u32 min_turn_time;
  682. __u32 speed;
  683. /* Get QoS values.  */
  684. speed = qos->baud_rate.value;
  685. min_turn_time = qos->min_turn_time.value;
  686. /* No need to calculate XBOFs for speeds over 115200 bps */
  687. if (speed > 115200) {
  688. self->mtt_required = min_turn_time;
  689. return;
  690. }
  691. /*  
  692.  *  Send additional BOF's for the next frame for the requested
  693.  *  min turn time, so now we must calculate how many chars (XBOF's) we 
  694.  *  must send for the requested time period (min turn time)
  695.  */
  696. self->xbofs_delay = irlap_min_turn_time_in_bytes(speed, min_turn_time);
  697. }
  698. /*
  699.  * Function irlap_flush_all_queues (void)
  700.  *
  701.  *    Flush all queues
  702.  *
  703.  */
  704. void irlap_flush_all_queues(struct irlap_cb *self) 
  705. {
  706. struct sk_buff* skb;
  707. ASSERT(self != NULL, return;);
  708. ASSERT(self->magic == LAP_MAGIC, return;);
  709. /* Free transmission queue */
  710. while ((skb = skb_dequeue(&self->txq)) != NULL)
  711. dev_kfree_skb(skb);
  712. while ((skb = skb_dequeue(&self->txq_ultra)) != NULL)
  713. dev_kfree_skb(skb);
  714. /* Free sliding window buffered packets */
  715. while ((skb = skb_dequeue(&self->wx_list)) != NULL)
  716. dev_kfree_skb(skb);
  717. }
  718. /*
  719.  * Function irlap_setspeed (self, speed)
  720.  *
  721.  *    Change the speed of the IrDA port
  722.  *
  723.  */
  724. void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
  725. {
  726. struct sk_buff *skb;
  727. IRDA_DEBUG(0, __FUNCTION__ "(), setting speed to %dn", speed);
  728. ASSERT(self != NULL, return;);
  729. ASSERT(self->magic == LAP_MAGIC, return;);
  730. self->speed = speed;
  731. /* Change speed now, or just piggyback speed on frames */
  732. if (now) {
  733. /* Send down empty frame to trigger speed change */
  734. skb = dev_alloc_skb(0);
  735. irlap_queue_xmit(self, skb);
  736. }
  737. }
  738. /*
  739.  * Function irlap_init_qos_capabilities (self, qos)
  740.  *
  741.  *    Initialize QoS for this IrLAP session, What we do is to compute the
  742.  *    intersection of the QoS capabilities for the user, driver and for
  743.  *    IrLAP itself. Normally, IrLAP will not specify any values, but it can
  744.  *    be used to restrict certain values.
  745.  */
  746. void irlap_init_qos_capabilities(struct irlap_cb *self,
  747.  struct qos_info *qos_user)
  748. {
  749. ASSERT(self != NULL, return;);
  750. ASSERT(self->magic == LAP_MAGIC, return;);
  751. ASSERT(self->netdev != NULL, return;);
  752. /* Start out with the maximum QoS support possible */
  753. irda_init_max_qos_capabilies(&self->qos_rx);
  754. /* Apply drivers QoS capabilities */
  755. irda_qos_compute_intersection(&self->qos_rx, self->qos_dev);
  756. /*
  757.  *  Check for user supplied QoS parameters. The service user is only 
  758.  *  allowed to supply these values. We check each parameter since the
  759.  *  user may not have set all of them.
  760.  */
  761. if (qos_user) {
  762. IRDA_DEBUG(1, __FUNCTION__ "(), Found user specified QoS!n");
  763. if (qos_user->baud_rate.bits)
  764. self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
  765. if (qos_user->max_turn_time.bits)
  766. self->qos_rx.max_turn_time.bits &= qos_user->max_turn_time.bits;
  767. if (qos_user->data_size.bits)
  768. self->qos_rx.data_size.bits &= qos_user->data_size.bits;
  769. if (qos_user->link_disc_time.bits)
  770. self->qos_rx.link_disc_time.bits &= qos_user->link_disc_time.bits;
  771. }
  772. /* Use 500ms in IrLAP for now */
  773. self->qos_rx.max_turn_time.bits &= 0x01;
  774. /* Set data size */
  775. /*self->qos_rx.data_size.bits &= 0x03;*/
  776. irda_qos_bits_to_value(&self->qos_rx);
  777. }
  778. /*
  779.  * Function irlap_apply_default_connection_parameters (void, now)
  780.  *
  781.  *    Use the default connection and transmission parameters
  782.  * 
  783.  */
  784. void irlap_apply_default_connection_parameters(struct irlap_cb *self)
  785. {
  786. IRDA_DEBUG(4, __FUNCTION__ "()n");
  787. ASSERT(self != NULL, return;);
  788. ASSERT(self->magic == LAP_MAGIC, return;);
  789. /* xbofs : Default value in NDM */
  790. self->next_bofs   = 12;
  791. self->bofs_count  = 12;
  792. /* NDM Speed is 9600 */
  793. irlap_change_speed(self, 9600, TRUE);
  794. /* Set mbusy when going to NDM state */
  795. irda_device_set_media_busy(self->netdev, TRUE);
  796. /* 
  797.  * Generate random connection address for this session, which must
  798.  * be 7 bits wide and different from 0x00 and 0xfe 
  799.  */
  800. while ((self->caddr == 0x00) || (self->caddr == 0xfe)) {
  801. get_random_bytes(&self->caddr, sizeof(self->caddr));
  802. self->caddr &= 0xfe;
  803. }
  804. /* Use default values until connection has been negitiated */
  805. self->slot_timeout = sysctl_slot_timeout;
  806. self->final_timeout = FINAL_TIMEOUT;
  807. self->poll_timeout = POLL_TIMEOUT;
  808. self->wd_timeout = WD_TIMEOUT;
  809. /* Set some default values */
  810. self->qos_tx.baud_rate.value = 9600;
  811. self->qos_rx.baud_rate.value = 9600;
  812. self->qos_tx.max_turn_time.value = 0;
  813. self->qos_rx.max_turn_time.value = 0;
  814. self->qos_tx.min_turn_time.value = 0;
  815. self->qos_rx.min_turn_time.value = 0;
  816. self->qos_tx.data_size.value = 64;
  817. self->qos_rx.data_size.value = 64;
  818. self->qos_tx.window_size.value = 1;
  819. self->qos_rx.window_size.value = 1;
  820. self->qos_tx.additional_bofs.value = 12;
  821. self->qos_rx.additional_bofs.value = 12;
  822. self->qos_tx.link_disc_time.value = 0;
  823. self->qos_rx.link_disc_time.value = 0;
  824. irlap_flush_all_queues(self);
  825. self->disconnect_pending = FALSE;
  826. self->connect_pending = FALSE;
  827. }
  828. /*
  829.  * Function irlap_apply_connection_parameters (qos, now)
  830.  *
  831.  *    Initialize IrLAP with the negotiated QoS values
  832.  *
  833.  * If 'now' is false, the speed and xbofs will be changed after the next
  834.  * frame is sent.
  835.  * If 'now' is true, the speed and xbofs is changed immediately
  836.  */
  837. void irlap_apply_connection_parameters(struct irlap_cb *self, int now) 
  838. {
  839. IRDA_DEBUG(4, __FUNCTION__ "()n");
  840. ASSERT(self != NULL, return;);
  841. ASSERT(self->magic == LAP_MAGIC, return;);
  842. /* Set the negociated xbofs value */
  843. self->next_bofs   = self->qos_tx.additional_bofs.value;
  844. if (now)
  845. self->bofs_count = self->next_bofs;
  846. /* Set the negociated link speed (may need the new xbofs value) */
  847. irlap_change_speed(self, self->qos_tx.baud_rate.value, now);
  848. self->window_size = self->qos_tx.window_size.value;
  849. self->window      = self->qos_tx.window_size.value;
  850. /*
  851.  *  Calculate how many bytes it is possible to transmit before the
  852.  *  link must be turned around
  853.  */
  854. self->line_capacity = 
  855. irlap_max_line_capacity(self->qos_tx.baud_rate.value,
  856. self->qos_tx.max_turn_time.value);
  857. /* 
  858.  *  Initialize timeout values, some of the rules are listed on 
  859.  *  page 92 in IrLAP.
  860.  */
  861. ASSERT(self->qos_tx.max_turn_time.value != 0, return;);
  862. ASSERT(self->qos_rx.max_turn_time.value != 0, return;);
  863. /* The poll timeout applies only to the primary station.
  864.  * It defines the maximum time the primary stay in XMIT mode
  865.  * before timeout and turning the link around (sending a RR).
  866.  * Or, this is how much we can keep the pf bit in primary mode.
  867.  * Therefore, it must be lower or equal than our *OWN* max turn around.
  868.  * Jean II */
  869. self->poll_timeout = self->qos_tx.max_turn_time.value * HZ / 1000;
  870. /* The Final timeout applies only to the primary station.
  871.  * It defines the maximum time the primary wait (mostly in RECV mode)
  872.  * for an answer from the secondary station before polling it again.
  873.  * Therefore, it must be greater or equal than our *PARTNER*
  874.  * max turn around time - Jean II */
  875. self->final_timeout = self->qos_rx.max_turn_time.value * HZ / 1000;
  876. /* The Watchdog Bit timeout applies only to the secondary station.
  877.  * It defines the maximum time the secondary wait (mostly in RECV mode)
  878.  * for poll from the primary station before getting annoyed.
  879.  * Therefore, it must be greater or equal than our *PARTNER*
  880.  * max turn around time - Jean II */
  881. self->wd_timeout = self->final_timeout * 2;
  882. /*
  883.  * N1 and N2 are maximum retry count for *both* the final timer
  884.  * and the wd timer (with a factor 2) as defined above.
  885.  * After N1 retry of a timer, we give a warning to the user.
  886.  * After N2 retry, we consider the link dead and disconnect it.
  887.  * Jean II
  888.  */
  889. /*
  890.  *  Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to 
  891.  *  3 seconds otherwise. See page 71 in IrLAP for more details.
  892.  *  Actually, it's not always 3 seconds, as we allow to set
  893.  *  it via sysctl... Max maxtt is 500ms, and N1 need to be multiple
  894.  *  of 2, so 1 second is minimum we can allow. - Jean II
  895.  */
  896. if (self->qos_tx.link_disc_time.value == sysctl_warn_noreply_time)
  897. /* 
  898.  * If we set N1 to 0, it will trigger immediately, which is
  899.  * not what we want. What we really want is to disable it,
  900.  * Jean II 
  901.  */
  902. self->N1 = -2; /* Disable - Need to be multiple of 2*/
  903. else
  904. self->N1 = sysctl_warn_noreply_time * 1000 /
  905.   self->qos_rx.max_turn_time.value;
  906. IRDA_DEBUG(4, "Setting N1 = %dn", self->N1);
  907. /* Set N2 to match our own disconnect time */
  908. self->N2 = self->qos_tx.link_disc_time.value * 1000 / 
  909. self->qos_rx.max_turn_time.value;
  910. IRDA_DEBUG(4, "Setting N2 = %dn", self->N2);
  911. }
  912. /*
  913.  * Function irlap_set_local_busy (self, status)
  914.  *
  915.  *    
  916.  *
  917.  */
  918. void irlap_set_local_busy(struct irlap_cb *self, int status)
  919. {
  920. IRDA_DEBUG(0, __FUNCTION__ "()n");
  921. self->local_busy = status;
  922. if (status)
  923. IRDA_DEBUG(0, __FUNCTION__ "(), local busy ONn");
  924. else
  925. IRDA_DEBUG(0, __FUNCTION__ "(), local busy OFFn");
  926. }
  927. #ifdef CONFIG_PROC_FS
  928. /*
  929.  * Function irlap_proc_read (buf, start, offset, len, unused)
  930.  *
  931.  *    Give some info to the /proc file system
  932.  *
  933.  */
  934. int irlap_proc_read(char *buf, char **start, off_t offset, int len)
  935. {
  936. struct irlap_cb *self;
  937. unsigned long flags;
  938. int i = 0;
  939.      
  940. save_flags(flags);
  941. cli();
  942. len = 0;
  943. self = (struct irlap_cb *) hashbin_get_first(irlap);
  944. while (self != NULL) {
  945. ASSERT(self != NULL, return -ENODEV;);
  946. ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
  947. len += sprintf(buf+len, "irlap%d ", i++);
  948. len += sprintf(buf+len, "state: %sn", 
  949.        irlap_state[self->state]);
  950. len += sprintf(buf+len, "  device name: %s, ",
  951.        (self->netdev) ? self->netdev->name : "bug");
  952. len += sprintf(buf+len, "hardware name: %sn", self->hw_name);
  953. len += sprintf(buf+len, "  caddr: %#02x, ", self->caddr);
  954. len += sprintf(buf+len, "saddr: %#08x, ", self->saddr);
  955. len += sprintf(buf+len, "daddr: %#08xn", self->daddr);
  956. len += sprintf(buf+len, "  win size: %d, ", 
  957.        self->window_size);
  958. len += sprintf(buf+len, "win: %d, ", self->window);
  959. #if CONFIG_IRDA_DYNAMIC_WINDOW
  960. len += sprintf(buf+len, "line capacity: %d, ", 
  961.        self->line_capacity);
  962. len += sprintf(buf+len, "bytes left: %dn", self->bytes_left);
  963. #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
  964. len += sprintf(buf+len, "  tx queue len: %d ", 
  965.        skb_queue_len(&self->txq));
  966. len += sprintf(buf+len, "win queue len: %d ", 
  967.        skb_queue_len(&self->wx_list));
  968. len += sprintf(buf+len, "rbusy: %s", self->remote_busy ?
  969.        "TRUE" : "FALSE");
  970. len += sprintf(buf+len, " mbusy: %sn", self->media_busy ?
  971.        "TRUE" : "FALSE");
  972. len += sprintf(buf+len, "  retrans: %d ", self->retry_count);
  973. len += sprintf(buf+len, "vs: %d ", self->vs);
  974. len += sprintf(buf+len, "vr: %d ", self->vr);
  975. len += sprintf(buf+len, "va: %dn", self->va);
  976. len += sprintf(buf+len, "  qostbpstmaxtttdsizetwinsizetaddbofstmintttldisctcompn");
  977. len += sprintf(buf+len, "  txt%dt", 
  978.        self->qos_tx.baud_rate.value);
  979. len += sprintf(buf+len, "%dt", 
  980.        self->qos_tx.max_turn_time.value);
  981. len += sprintf(buf+len, "%dt",
  982.        self->qos_tx.data_size.value);
  983. len += sprintf(buf+len, "%dt",
  984.        self->qos_tx.window_size.value);
  985. len += sprintf(buf+len, "%dt",
  986.        self->qos_tx.additional_bofs.value);
  987. len += sprintf(buf+len, "%dt", 
  988.        self->qos_tx.min_turn_time.value);
  989. len += sprintf(buf+len, "%dt", 
  990.        self->qos_tx.link_disc_time.value);
  991. len += sprintf(buf+len, "n");
  992. len += sprintf(buf+len, "  rxt%dt", 
  993.        self->qos_rx.baud_rate.value);
  994. len += sprintf(buf+len, "%dt", 
  995.        self->qos_rx.max_turn_time.value);
  996. len += sprintf(buf+len, "%dt",
  997.        self->qos_rx.data_size.value);
  998. len += sprintf(buf+len, "%dt",
  999.        self->qos_rx.window_size.value);
  1000. len += sprintf(buf+len, "%dt",
  1001.        self->qos_rx.additional_bofs.value);
  1002. len += sprintf(buf+len, "%dt", 
  1003.        self->qos_rx.min_turn_time.value);
  1004. len += sprintf(buf+len, "%dt", 
  1005.        self->qos_rx.link_disc_time.value);
  1006. len += sprintf(buf+len, "n");
  1007. self = (struct irlap_cb *) hashbin_get_next(irlap);
  1008. }
  1009. restore_flags(flags);
  1010. return len;
  1011. }
  1012. #endif /* CONFIG_PROC_FS */