00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <linux/config.h>
00032 #include <linux/malloc.h>
00033 #include <linux/string.h>
00034 #include <linux/skbuff.h>
00035 #include <linux/delay.h>
00036 #include <linux/proc_fs.h>
00037 #include <linux/init.h>
00038 #include <linux/random.h>
00039
00040 #include <net/irda/irda.h>
00041 #include <net/irda/irda_device.h>
00042 #include <net/irda/irqueue.h>
00043 #include <net/irda/irlmp.h>
00044 #include <net/irda/irlmp_frame.h>
00045 #include <net/irda/irlap_frame.h>
00046 #include <net/irda/irlap.h>
00047 #include <net/irda/timer.h>
00048 #include <net/irda/qos.h>
00049 #include <net/irda/irlap_comp.h>
00050
00051 hashbin_t *irlap = NULL;
00052 int sysctl_slot_timeout = SLOT_TIMEOUT * 1000 / HZ;
00053
00054 static void __irlap_close(struct irlap_cb *self);
00055
00056 static char *lap_reasons[] = {
00057 "ERROR, NOT USED",
00058 "LAP_DISC_INDICATION",
00059 "LAP_NO_RESPONSE",
00060 "LAP_RESET_INDICATION",
00061 "LAP_FOUND_NONE",
00062 "LAP_MEDIA_BUSY",
00063 "LAP_PRIMARY_CONFLICT",
00064 "ERROR, NOT USED",
00065 };
00066
00067 #ifdef CONFIG_PROC_FS
00068 int irlap_proc_read(char *, char **, off_t, int, int);
00069
00070 #endif
00071
00072 int __init irlap_init(void)
00073 {
00074
00075 irlap = hashbin_new(HB_LOCAL);
00076 if (irlap == NULL) {
00077 ERROR(__FUNCTION__ "(), can't allocate irlap hashbin!\n");
00078 return -ENOMEM;
00079 }
00080
00081 #ifdef CONFIG_IRDA_COMPRESSION
00082 irlap_compressors = hashbin_new(HB_LOCAL);
00083 if (irlap_compressors == NULL) {
00084 WARNING(__FUNCTION__
00085 "(), can't allocate compressors hashbin!\n");
00086 return -ENOMEM;
00087 }
00088 #endif
00089
00090 return 0;
00091 }
00092
00093 void irlap_cleanup(void)
00094 {
00095 ASSERT(irlap != NULL, return;);
00096
00097 hashbin_delete(irlap, (FREE_FUNC) __irlap_close);
00098
00099 #ifdef CONFIG_IRDA_COMPRESSION
00100 hashbin_delete(irlap_compressors, (FREE_FUNC) kfree);
00101 #endif
00102 }
00103
00104
00105
00106
00107
00108
00109
00110 struct irlap_cb *irlap_open(struct device *dev, struct qos_info *qos)
00111 {
00112 struct irlap_cb *self;
00113
00114 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00115
00116
00117 self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);
00118 if (self == NULL)
00119 return NULL;
00120
00121 memset(self, 0, sizeof(struct irlap_cb));
00122 self->magic = LAP_MAGIC;
00123
00124
00125 self->netdev = dev;
00126 self->qos_dev = qos;
00127
00128
00129 dev->atalk_ptr = self;
00130
00131 irlap_next_state(self, LAP_OFFLINE);
00132
00133
00134 skb_queue_head_init(&self->txq);
00135 skb_queue_head_init(&self->txq_ultra);
00136 skb_queue_head_init(&self->wx_list);
00137
00138
00139 get_random_bytes(&self->saddr, sizeof(self->saddr));
00140 memcpy(dev->dev_addr, &self->saddr, 4);
00141
00142 init_timer(&self->slot_timer);
00143 init_timer(&self->query_timer);
00144 init_timer(&self->discovery_timer);
00145 init_timer(&self->final_timer);
00146 init_timer(&self->poll_timer);
00147 init_timer(&self->wd_timer);
00148 init_timer(&self->backoff_timer);
00149 init_timer(&self->media_busy_timer);
00150
00151 irlap_apply_default_connection_parameters(self);
00152
00153 self->N3 = 3;
00154
00155 irlap_next_state(self, LAP_NDM);
00156
00157 hashbin_insert(irlap, (queue_t *) self, self->saddr, NULL);
00158
00159 irlmp_register_link(self, self->saddr, &self->notify);
00160
00161 return self;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170 static void __irlap_close(struct irlap_cb *self)
00171 {
00172 ASSERT(self != NULL, return;);
00173 ASSERT(self->magic == LAP_MAGIC, return;);
00174
00175
00176 del_timer(&self->slot_timer);
00177 del_timer(&self->query_timer);
00178 del_timer(&self->discovery_timer);
00179 del_timer(&self->final_timer);
00180 del_timer(&self->poll_timer);
00181 del_timer(&self->wd_timer);
00182 del_timer(&self->backoff_timer);
00183 del_timer(&self->media_busy_timer);
00184
00185 irlap_flush_all_queues(self);
00186
00187 self->magic = 0;
00188
00189 kfree(self);
00190 }
00191
00192
00193
00194
00195
00196
00197
00198 void irlap_close(struct irlap_cb *self)
00199 {
00200 struct irlap_cb *lap;
00201
00202 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00203
00204 ASSERT(self != NULL, return;);
00205 ASSERT(self->magic == LAP_MAGIC, return;);
00206
00207 irlap_disconnect_indication(self, LAP_DISC_INDICATION);
00208
00209 irlmp_unregister_link(self->saddr);
00210 self->notify.instance = NULL;
00211
00212
00213 lap = hashbin_remove(irlap, self->saddr, NULL);
00214 if (!lap) {
00215 IRDA_DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");
00216 return;
00217 }
00218 __irlap_close(lap);
00219 }
00220
00221
00222
00223
00224
00225
00226
00227 void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb)
00228 {
00229 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00230
00231 ASSERT(self != NULL, return;);
00232 ASSERT(self->magic == LAP_MAGIC, return;);
00233
00234 irlap_init_qos_capabilities(self, NULL);
00235
00236 irlmp_link_connect_indication(self->notify.instance, self->saddr,
00237 self->daddr, &self->qos_tx, skb);
00238 }
00239
00240
00241
00242
00243
00244
00245
00246 void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb)
00247 {
00248 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00249
00250 irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260 void irlap_connect_request(struct irlap_cb *self, __u32 daddr,
00261 struct qos_info *qos_user, int sniff)
00262 {
00263 IRDA_DEBUG(3, __FUNCTION__ "(), daddr=0x%08x\n", daddr);
00264
00265 ASSERT(self != NULL, return;);
00266 ASSERT(self->magic == LAP_MAGIC, return;);
00267
00268 self->daddr = daddr;
00269
00270
00271
00272
00273
00274 irlap_init_qos_capabilities(self, qos_user);
00275
00276 if ((self->state == LAP_NDM) && !self->media_busy)
00277 irlap_do_event(self, CONNECT_REQUEST, NULL, NULL);
00278 else
00279 self->connect_pending = TRUE;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288 void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
00289 {
00290 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00291
00292 ASSERT(self != NULL, return;);
00293 ASSERT(self->magic == LAP_MAGIC, return;);
00294
00295 irlmp_link_connect_confirm(self->notify.instance, &self->qos_tx, skb);
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305 void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb,
00306 int unreliable)
00307 {
00308
00309 skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
00310
00311 #ifdef CONFIG_IRDA_COMPRESSION
00312 if (self->qos_tx.compression.value) {
00313 skb = irlap_decompress_frame(self, skb);
00314 if (!skb) {
00315 IRDA_DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
00316 return;
00317 }
00318 }
00319 #endif
00320 irlmp_link_data_indication(self->notify.instance, skb, unreliable);
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330 void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
00331 int unreliable)
00332 {
00333 ASSERT(self != NULL, return;);
00334 ASSERT(self->magic == LAP_MAGIC, return;);
00335
00336 IRDA_DEBUG(3, __FUNCTION__ "()\n");
00337
00338 #ifdef CONFIG_IRDA_COMPRESSION
00339 if (self->qos_tx.compression.value) {
00340 skb = irlap_compress_frame(self, skb);
00341 if (!skb) {
00342 IRDA_DEBUG(1, __FUNCTION__ "(), Compress error!\n");
00343 return;
00344 }
00345 }
00346 #endif
00347 ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
00348 return;);
00349 skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
00350
00351
00352
00353
00354
00355 if (unreliable)
00356 skb->data[1] = UI_FRAME;
00357 else
00358 skb->data[1] = I_FRAME;
00359
00360
00361
00362
00363
00364 if ((self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) {
00365
00366
00367
00368
00369 if (!skb_queue_empty(&self->txq)) {
00370 skb_queue_tail(&self->txq, skb);
00371 skb = skb_dequeue(&self->txq);
00372
00373 ASSERT(skb != NULL, return;);
00374 }
00375 irlap_do_event(self, SEND_I_CMD, skb, NULL);
00376 } else
00377 skb_queue_tail(&self->txq, skb);
00378 }
00379
00380
00381
00382
00383
00384
00385
00386 #ifdef CONFIG_IRDA_ULTRA
00387 void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
00388 {
00389 ASSERT(self != NULL, return;);
00390 ASSERT(self->magic == LAP_MAGIC, return;);
00391
00392 IRDA_DEBUG(3, __FUNCTION__ "()\n");
00393
00394 ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
00395 return;);
00396 skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
00397
00398 skb->data[0] = CBROADCAST;
00399 skb->data[1] = UI_FRAME;
00400
00401 skb_queue_tail(&self->txq_ultra, skb);
00402
00403 irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);
00404 }
00405 #endif
00406
00407
00408
00409
00410
00411
00412
00413 #ifdef CONFIG_IRDA_ULTRA
00414 void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
00415 {
00416 IRDA_DEBUG(1, __FUNCTION__ "()\n");
00417
00418 ASSERT(self != NULL, return;);
00419 ASSERT(self->magic == LAP_MAGIC, return;);
00420 ASSERT(skb != NULL, return;);
00421
00422
00423 skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
00424
00425 irlmp_link_unitdata_indication(self->notify.instance, skb);
00426 }
00427 #endif
00428
00429
00430
00431
00432
00433
00434 void irlap_disconnect_request(struct irlap_cb *self)
00435 {
00436 IRDA_DEBUG(3, __FUNCTION__ "()\n");
00437
00438 ASSERT(self != NULL, return;);
00439 ASSERT(self->magic == LAP_MAGIC, return;);
00440
00441
00442 if (skb_queue_len(&self->txq) > 0) {
00443 self->disconnect_pending = TRUE;
00444
00445 return;
00446 }
00447
00448
00449 switch (self->state) {
00450 case LAP_XMIT_P:
00451 case LAP_XMIT_S:
00452 case LAP_CONN:
00453 case LAP_RESET_WAIT:
00454 case LAP_RESET_CHECK:
00455 irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
00456 break;
00457 default:
00458 IRDA_DEBUG(2, __FUNCTION__ "(), disconnect pending!\n");
00459 self->disconnect_pending = TRUE;
00460 break;
00461 }
00462 }
00463
00464
00465
00466
00467
00468
00469
00470 void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
00471 {
00472 IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]);
00473
00474 ASSERT(self != NULL, return;);
00475 ASSERT(self->magic == LAP_MAGIC, return;);
00476
00477 #ifdef CONFIG_IRDA_COMPRESSION
00478 irda_free_compression(self);
00479 #endif
00480
00481 irlap_flush_all_queues(self);
00482
00483 switch (reason) {
00484 case LAP_RESET_INDICATION:
00485 IRDA_DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
00486 irlap_do_event(self, RESET_REQUEST, NULL, NULL);
00487 break;
00488 case LAP_NO_RESPONSE:
00489 case LAP_DISC_INDICATION:
00490 case LAP_FOUND_NONE:
00491 case LAP_MEDIA_BUSY:
00492 irlmp_link_disconnect_indication(self->notify.instance, self,
00493 reason, NULL);
00494 break;
00495 default:
00496 ERROR(__FUNCTION__ "(), Unknown reason %d\n", reason);
00497 }
00498 }
00499
00500
00501
00502
00503
00504
00505
00506 void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
00507 {
00508 struct irlap_info info;
00509
00510 ASSERT(self != NULL, return;);
00511 ASSERT(self->magic == LAP_MAGIC, return;);
00512 ASSERT(discovery != NULL, return;);
00513
00514 IRDA_DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
00515
00516 ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
00517 (discovery->nslots == 8) || (discovery->nslots == 16),
00518 return;);
00519
00520
00521 if (self->state != LAP_NDM) {
00522 IRDA_DEBUG(4, __FUNCTION__
00523 "(), discovery only possible in NDM mode\n");
00524 irlap_discovery_confirm(self, NULL);
00525 return;
00526 }
00527
00528
00529 if (self->discovery_log != NULL) {
00530 hashbin_delete(self->discovery_log, (FREE_FUNC) kfree);
00531 self->discovery_log = NULL;
00532 }
00533
00534 self->discovery_log= hashbin_new(HB_LOCAL);
00535
00536 info.S = discovery->nslots;
00537 info.s = 0;
00538
00539 self->discovery_cmd = discovery;
00540 info.discovery = discovery;
00541
00542
00543 if (sysctl_slot_timeout < 20) {
00544 ERROR(__FUNCTION__
00545 "(), to low value for slot timeout!\n");
00546 sysctl_slot_timeout = 20;
00547 }
00548
00549
00550
00551
00552 if (sysctl_slot_timeout > 160) {
00553 ERROR(__FUNCTION__
00554 "(), to high value for slot timeout!\n");
00555 sysctl_slot_timeout = 160;
00556 }
00557
00558 self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
00559
00560 irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
00561 }
00562
00563
00564
00565
00566
00567
00568
00569 void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log)
00570 {
00571 ASSERT(self != NULL, return;);
00572 ASSERT(self->magic == LAP_MAGIC, return;);
00573
00574 ASSERT(self->notify.instance != NULL, return;);
00575
00576
00577
00578
00579
00580
00581 if (discovery_log && HASHBIN_GET_SIZE(discovery_log) > 0)
00582 irda_device_set_media_busy(self->netdev, FALSE);
00583
00584
00585 irlmp_link_discovery_confirm(self->notify.instance, discovery_log);
00586 }
00587
00588
00589
00590
00591
00592
00593
00594 void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery)
00595 {
00596 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00597
00598 ASSERT(self != NULL, return;);
00599 ASSERT(self->magic == LAP_MAGIC, return;);
00600 ASSERT(discovery != NULL, return;);
00601
00602 ASSERT(self->notify.instance != NULL, return;);
00603
00604 irlmp_link_discovery_indication(self->notify.instance, discovery);
00605 }
00606
00607
00608
00609
00610
00611
00612
00613 void irlap_status_indication(int quality_of_link)
00614 {
00615 switch (quality_of_link) {
00616 case STATUS_NO_ACTIVITY:
00617 MESSAGE("IrLAP, no activity on link!\n");
00618 break;
00619 case STATUS_NOISY:
00620 MESSAGE("IrLAP, noisy link!\n");
00621 break;
00622 default:
00623 break;
00624 }
00625 irlmp_status_indication(quality_of_link, LOCK_NO_CHANGE);
00626 }
00627
00628
00629
00630
00631
00632
00633
00634 void irlap_reset_indication(struct irlap_cb *self)
00635 {
00636 IRDA_DEBUG(1, __FUNCTION__ "()\n");
00637
00638 ASSERT(self != NULL, return;);
00639 ASSERT(self->magic == LAP_MAGIC, return;);
00640
00641 if (self->state == LAP_RESET_WAIT)
00642 irlap_do_event(self, RESET_REQUEST, NULL, NULL);
00643 else
00644 irlap_do_event(self, RESET_RESPONSE, NULL, NULL);
00645 }
00646
00647
00648
00649
00650
00651
00652
00653 void irlap_reset_confirm(void)
00654 {
00655 IRDA_DEBUG(1, __FUNCTION__ "()\n");
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665 int irlap_generate_rand_time_slot(int S, int s)
00666 {
00667 int slot;
00668
00669 ASSERT((S - s) > 0, return 0;);
00670
00671 slot = s + jiffies % (S-s);
00672
00673 ASSERT((slot >= s) || (slot < S), return 0;);
00674
00675 return slot;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685 void irlap_update_nr_received(struct irlap_cb *self, int nr)
00686 {
00687 struct sk_buff *skb = NULL;
00688 int count = 0;
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 if (nr == self->vs) {
00700 while ((skb = skb_dequeue(&self->wx_list)) != NULL) {
00701 dev_kfree_skb(skb);
00702 }
00703
00704 self->va = nr - 1;
00705 } else {
00706
00707 while ((skb_peek(&self->wx_list) != NULL) &&
00708 (((self->va+1) % 8) != nr))
00709 {
00710 skb = skb_dequeue(&self->wx_list);
00711 dev_kfree_skb(skb);
00712
00713 self->va = (self->va + 1) % 8;
00714 count++;
00715 }
00716 }
00717
00718
00719 self->window = self->window_size - skb_queue_len(&self->wx_list);
00720 }
00721
00722
00723
00724
00725
00726
00727 int irlap_validate_ns_received(struct irlap_cb *self, int ns)
00728 {
00729
00730 if (ns == self->vr)
00731 return NS_EXPECTED;
00732
00733
00734
00735
00736 return NS_UNEXPECTED;
00737
00738
00739 }
00740
00741
00742
00743
00744
00745
00746 int irlap_validate_nr_received(struct irlap_cb *self, int nr)
00747 {
00748
00749 if (nr == self->vs) {
00750 IRDA_DEBUG(4, __FUNCTION__ "(), expected!\n");
00751 return NR_EXPECTED;
00752 }
00753
00754
00755
00756
00757
00758 if (self->va < self->vs) {
00759 if ((nr >= self->va) && (nr <= self->vs))
00760 return NR_UNEXPECTED;
00761 } else {
00762 if ((nr >= self->va) || (nr <= self->vs))
00763 return NR_UNEXPECTED;
00764 }
00765
00766
00767 return NR_INVALID;
00768 }
00769
00770
00771
00772
00773
00774
00775
00776 void irlap_initiate_connection_state(struct irlap_cb *self)
00777 {
00778 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00779
00780 ASSERT(self != NULL, return;);
00781 ASSERT(self->magic == LAP_MAGIC, return;);
00782
00783
00784 self->vs = self->vr = 0;
00785
00786
00787 self->va = 7;
00788
00789 self->window = 1;
00790
00791 self->remote_busy = FALSE;
00792 self->retry_count = 0;
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 void irlap_wait_min_turn_around(struct irlap_cb *self, struct qos_info *qos)
00804 {
00805 __u32 min_turn_time;
00806 __u32 speed;
00807
00808
00809 speed = qos->baud_rate.value;
00810 min_turn_time = qos->min_turn_time.value;
00811
00812
00813 if (speed > 115200) {
00814 self->mtt_required = min_turn_time;
00815 return;
00816 }
00817
00818
00819
00820
00821
00822
00823 self->xbofs_delay = irlap_min_turn_time_in_bytes(speed, min_turn_time);
00824 }
00825
00826
00827
00828
00829
00830
00831
00832 void irlap_flush_all_queues(struct irlap_cb *self)
00833 {
00834 struct sk_buff* skb;
00835
00836 ASSERT(self != NULL, return;);
00837 ASSERT(self->magic == LAP_MAGIC, return;);
00838
00839
00840 while ((skb = skb_dequeue(&self->txq)) != NULL)
00841 dev_kfree_skb(skb);
00842
00843 while ((skb = skb_dequeue(&self->txq_ultra)) != NULL)
00844 dev_kfree_skb(skb);
00845
00846
00847 while ((skb = skb_dequeue(&self->wx_list)) != NULL)
00848 dev_kfree_skb(skb);
00849
00850 #ifdef CONFIG_IRDA_RECYCLE_RR
00851 if (self->recycle_rr_skb) {
00852 dev_kfree_skb(self->recycle_rr_skb);
00853 self->recycle_rr_skb = NULL;
00854 }
00855 #endif
00856 }
00857
00858
00859
00860
00861
00862
00863
00864 void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
00865 {
00866 IRDA_DEBUG(0, __FUNCTION__ "(), setting speed to %d\n", speed);
00867
00868 ASSERT(self != NULL, return;);
00869 ASSERT(self->magic == LAP_MAGIC, return;);
00870
00871 self->speed = speed;
00872
00873
00874 if (now)
00875 irda_device_change_speed(self->netdev, speed);
00876 }
00877
00878 #ifdef CONFIG_IRDA_COMPRESSION
00879 void irlap_init_comp_qos_capabilities(struct irlap_cb *self)
00880 {
00881 struct irda_compressor *comp;
00882 __u8 mask;
00883 int i;
00884
00885 ASSERT(self != NULL, return;);
00886 ASSERT(self->magic == LAP_MAGIC, return;);
00887
00888
00889
00890
00891
00892
00893
00894 IRDA_DEBUG(4, __FUNCTION__ "(), comp bits 0x%02x\n",
00895 self->qos_rx.compression.bits);
00896 mask = 0x80;
00897 for (i=0;i<8;i++) {
00898 IRDA_DEBUG(4, __FUNCTION__ "(), testing bit %d\n", 8-i);
00899 if (self->qos_rx.compression.bits & mask) {
00900 IRDA_DEBUG(4, __FUNCTION__
00901 "(), bit %d is set by defalt\n", 8-i);
00902 comp = hashbin_find(irlap_compressors,
00903 compressions[msb_index(mask)],
00904 NULL);
00905 if (!comp) {
00906
00907 IRDA_DEBUG(4, __FUNCTION__ "(), Compression "
00908 "protocol %d has not been loaded!\n",
00909 compressions[msb_index(mask)]);
00910 self->qos_rx.compression.bits &= ~mask;
00911 IRDA_DEBUG(4, __FUNCTION__
00912 "(), comp bits 0x%02x\n",
00913 self->qos_rx.compression.bits);
00914 }
00915 }
00916
00917 mask >>= 1;
00918 }
00919 }
00920 #endif
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 void irlap_init_qos_capabilities(struct irlap_cb *self,
00931 struct qos_info *qos_user)
00932 {
00933 ASSERT(self != NULL, return;);
00934 ASSERT(self->magic == LAP_MAGIC, return;);
00935 ASSERT(self->netdev != NULL, return;);
00936
00937
00938 irda_init_max_qos_capabilies(&self->qos_rx);
00939
00940 #ifdef CONFIG_IRDA_COMPRESSION
00941 irlap_init_comp_qos_capabilities(self);
00942 #endif
00943
00944
00945 irda_qos_compute_intersection(&self->qos_rx, self->qos_dev);
00946
00947
00948
00949
00950
00951
00952 if (qos_user) {
00953 IRDA_DEBUG(1, __FUNCTION__ "(), Found user specified QoS!\n");
00954
00955 if (qos_user->baud_rate.bits)
00956 self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
00957
00958 if (qos_user->max_turn_time.bits)
00959 self->qos_rx.max_turn_time.bits &= qos_user->max_turn_time.bits;
00960 if (qos_user->data_size.bits)
00961 self->qos_rx.data_size.bits &= qos_user->data_size.bits;
00962
00963 if (qos_user->link_disc_time.bits)
00964 self->qos_rx.link_disc_time.bits &= qos_user->link_disc_time.bits;
00965 #ifdef CONFIG_IRDA_COMPRESSION
00966 self->qos_rx.compression.bits &= qos_user->compression.bits;
00967 #endif
00968 }
00969
00970
00971 self->qos_rx.max_turn_time.bits &= 0x01;
00972
00973
00974
00975
00976
00977 self->qos_rx.link_disc_time.bits &= 0x07;
00978
00979 irda_qos_bits_to_value(&self->qos_rx);
00980 }
00981
00982
00983
00984
00985
00986
00987
00988 void irlap_apply_default_connection_parameters(struct irlap_cb *self)
00989 {
00990 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00991
00992 ASSERT(self != NULL, return;);
00993 ASSERT(self->magic == LAP_MAGIC, return;);
00994
00995 irlap_change_speed(self, 9600, TRUE);
00996
00997
00998 irda_device_set_media_busy(self->netdev, TRUE);
00999
01000
01001 self->bofs_count = 11;
01002
01003
01004
01005
01006
01007 while ((self->caddr == 0x00) || (self->caddr == 0xfe)) {
01008 get_random_bytes(&self->caddr, sizeof(self->caddr));
01009 self->caddr &= 0xfe;
01010 }
01011
01012
01013 self->slot_timeout = sysctl_slot_timeout;
01014 self->final_timeout = FINAL_TIMEOUT;
01015 self->poll_timeout = POLL_TIMEOUT;
01016 self->wd_timeout = WD_TIMEOUT;
01017
01018
01019 self->qos_tx.baud_rate.value = 9600;
01020 self->qos_rx.baud_rate.value = 9600;
01021 self->qos_tx.max_turn_time.value = 0;
01022 self->qos_rx.max_turn_time.value = 0;
01023 self->qos_tx.min_turn_time.value = 0;
01024 self->qos_rx.min_turn_time.value = 0;
01025 self->qos_tx.data_size.value = 64;
01026 self->qos_rx.data_size.value = 64;
01027 self->qos_tx.window_size.value = 1;
01028 self->qos_rx.window_size.value = 1;
01029 self->qos_tx.additional_bofs.value = 11;
01030 self->qos_rx.additional_bofs.value = 11;
01031 self->qos_tx.link_disc_time.value = 0;
01032 self->qos_rx.link_disc_time.value = 0;
01033
01034 irlap_flush_all_queues(self);
01035
01036 self->disconnect_pending = FALSE;
01037 self->connect_pending = FALSE;
01038 }
01039
01040
01041
01042
01043
01044
01045
01046 void irlap_apply_connection_parameters(struct irlap_cb *self)
01047 {
01048 IRDA_DEBUG(4, __FUNCTION__ "()\n");
01049
01050 ASSERT(self != NULL, return;);
01051 ASSERT(self->magic == LAP_MAGIC, return;);
01052
01053 irlap_change_speed(self, self->qos_tx.baud_rate.value, FALSE);
01054
01055 self->window_size = self->qos_tx.window_size.value;
01056 self->window = self->qos_tx.window_size.value;
01057 self->bofs_count = self->qos_tx.additional_bofs.value;
01058
01059
01060
01061
01062
01063 self->line_capacity =
01064 irlap_max_line_capacity(self->qos_tx.baud_rate.value,
01065 self->qos_tx.max_turn_time.value);
01066
01067
01068
01069
01070
01071
01072 ASSERT(self->qos_tx.max_turn_time.value != 0, return;);
01073 if (self->qos_tx.link_disc_time.value == 3)
01074 self->N1 = 0;
01075 else
01076 self->N1 = 3000 / self->qos_tx.max_turn_time.value;
01077
01078 IRDA_DEBUG(4, "Setting N1 = %d\n", self->N1);
01079
01080
01081 self->N2 = self->qos_tx.link_disc_time.value * 1000 /
01082 self->qos_tx.max_turn_time.value;
01083 IRDA_DEBUG(4, "Setting N2 = %d\n", self->N2);
01084
01085
01086
01087
01088
01089 self->poll_timeout = self->qos_tx.max_turn_time.value * HZ / 1000;
01090 self->wd_timeout = self->poll_timeout * 2;
01091
01092
01093
01094
01095
01096 self->final_timeout = self->qos_rx.max_turn_time.value * HZ / 1000;
01097
01098 #ifdef CONFIG_IRDA_COMPRESSION
01099 if (self->qos_tx.compression.value) {
01100 IRDA_DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
01101 irda_set_compression(self, self->qos_tx.compression.value);
01102
01103 irlap_compressor_init(self, 0);
01104 }
01105 #endif
01106 }
01107
01108
01109
01110
01111
01112
01113
01114 void irlap_set_local_busy(struct irlap_cb *self, int status)
01115 {
01116 IRDA_DEBUG(0, __FUNCTION__ "()\n");
01117
01118 self->local_busy = status;
01119
01120 if (status)
01121 IRDA_DEBUG(0, __FUNCTION__ "(), local busy ON\n");
01122 else
01123 IRDA_DEBUG(0, __FUNCTION__ "(), local busy OFF\n");
01124 }
01125
01126 #ifdef CONFIG_PROC_FS
01127
01128
01129
01130
01131
01132
01133 int irlap_proc_read(char *buf, char **start, off_t offset, int len,
01134 int unused)
01135 {
01136 struct irlap_cb *self;
01137 unsigned long flags;
01138 int i = 0;
01139
01140 save_flags(flags);
01141 cli();
01142
01143 len = 0;
01144
01145 self = (struct irlap_cb *) hashbin_get_first(irlap);
01146 while (self != NULL) {
01147 ASSERT(self != NULL, return -ENODEV;);
01148 ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
01149
01150 len += sprintf(buf+len, "irlap%d ", i++);
01151 len += sprintf(buf+len, "state: %s\n",
01152 irlap_state[self->state]);
01153
01154 len += sprintf(buf+len, " caddr: %#02x, ", self->caddr);
01155 len += sprintf(buf+len, "saddr: %#08x, ", self->saddr);
01156 len += sprintf(buf+len, "daddr: %#08x\n", self->daddr);
01157
01158 len += sprintf(buf+len, " win size: %d, ",
01159 self->window_size);
01160 len += sprintf(buf+len, "win: %d, ", self->window);
01161 #if CONFIG_IRDA_DYNAMIC_WINDOW
01162 len += sprintf(buf+len, "line capacity: %d, ",
01163 self->line_capacity);
01164 len += sprintf(buf+len, "bytes left: %d\n", self->bytes_left);
01165 #endif
01166 len += sprintf(buf+len, " tx queue len: %d ",
01167 skb_queue_len(&self->txq));
01168 len += sprintf(buf+len, "win queue len: %d ",
01169 skb_queue_len(&self->wx_list));
01170 len += sprintf(buf+len, "rbusy: %s", self->remote_busy ?
01171 "TRUE" : "FALSE");
01172 len += sprintf(buf+len, " mbusy: %s\n", self->media_busy ?
01173 "TRUE" : "FALSE");
01174
01175 len += sprintf(buf+len, " retrans: %d ", self->retry_count);
01176 len += sprintf(buf+len, "vs: %d ", self->vs);
01177 len += sprintf(buf+len, "vr: %d ", self->vr);
01178 len += sprintf(buf+len, "va: %d\n", self->va);
01179
01180 len += sprintf(buf+len, " qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n");
01181
01182 len += sprintf(buf+len, " tx\t%d\t",
01183 self->qos_tx.baud_rate.value);
01184 len += sprintf(buf+len, "%d\t",
01185 self->qos_tx.max_turn_time.value);
01186 len += sprintf(buf+len, "%d\t",
01187 self->qos_tx.data_size.value);
01188 len += sprintf(buf+len, "%d\t",
01189 self->qos_tx.window_size.value);
01190 len += sprintf(buf+len, "%d\t",
01191 self->qos_tx.additional_bofs.value);
01192 len += sprintf(buf+len, "%d\t",
01193 self->qos_tx.min_turn_time.value);
01194 len += sprintf(buf+len, "%d\t",
01195 self->qos_tx.link_disc_time.value);
01196 #ifdef CONFIG_IRDA_COMPRESSION
01197 len += sprintf(buf+len, "%d",
01198 self->qos_tx.compression.value);
01199 #endif
01200 len += sprintf(buf+len, "\n");
01201
01202 len += sprintf(buf+len, " rx\t%d\t",
01203 self->qos_rx.baud_rate.value);
01204 len += sprintf(buf+len, "%d\t",
01205 self->qos_rx.max_turn_time.value);
01206 len += sprintf(buf+len, "%d\t",
01207 self->qos_rx.data_size.value);
01208 len += sprintf(buf+len, "%d\t",
01209 self->qos_rx.window_size.value);
01210 len += sprintf(buf+len, "%d\t",
01211 self->qos_rx.additional_bofs.value);
01212 len += sprintf(buf+len, "%d\t",
01213 self->qos_rx.min_turn_time.value);
01214 len += sprintf(buf+len, "%d\t",
01215 self->qos_rx.link_disc_time.value);
01216 #ifdef CONFIG_IRDA_COMPRESSION
01217 len += sprintf(buf+len, "%d",
01218 self->qos_rx.compression.value);
01219 #endif
01220 len += sprintf(buf+len, "\n");
01221
01222 self = (struct irlap_cb *) hashbin_get_next(irlap);
01223 }
01224 restore_flags(flags);
01225
01226 return len;
01227 }
01228
01229 #endif
01230