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 #include <linux/config.h>
00027 #include <linux/skbuff.h>
00028 #include <linux/init.h>
00029
00030 #include <asm/byteorder.h>
00031 #include <asm/unaligned.h>
00032
00033 #include <net/irda/irda.h>
00034 #include <net/irda/irmod.h>
00035 #include <net/irda/irlap.h>
00036 #include <net/irda/irlmp.h>
00037 #include <net/irda/parameters.h>
00038 #include <net/irda/irttp.h>
00039
00040 static struct irttp_cb *irttp = NULL;
00041
00042 static void __irttp_close_tsap(struct tsap_cb *self);
00043
00044 static int irttp_data_indication(void *instance, void *sap,
00045 struct sk_buff *skb);
00046 static int irttp_udata_indication(void *instance, void *sap,
00047 struct sk_buff *skb);
00048 static void irttp_disconnect_indication(void *instance, void *sap,
00049 LM_REASON reason, struct sk_buff *);
00050 static void irttp_connect_indication(void *instance, void *sap,
00051 struct qos_info *qos, __u32 max_sdu_size,
00052 __u8 header_size, struct sk_buff *skb);
00053 static void irttp_connect_confirm(void *instance, void *sap,
00054 struct qos_info *qos, __u32 max_sdu_size,
00055 __u8 header_size, struct sk_buff *skb);
00056 static void irttp_run_tx_queue(struct tsap_cb *self);
00057 static void irttp_run_rx_queue(struct tsap_cb *self);
00058
00059 static void irttp_flush_queues(struct tsap_cb *self);
00060 static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
00061 static void irttp_start_todo_timer(struct tsap_cb *self, int timeout);
00062 static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
00063 static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
00064 int get);
00065
00066
00067 static pi_minor_info_t pi_minor_call_table[] = {
00068 { NULL, 0 },
00069 { irttp_param_max_sdu_size, PV_INTEGER | PV_BIG_ENDIAN }
00070 };
00071 static pi_major_info_t pi_major_call_table[] = {{ pi_minor_call_table, 2 }};
00072 static pi_param_info_t param_info = { pi_major_call_table, 1, 0x0f, 4 };
00073
00074
00075
00076
00077
00078
00079
00080 int __init irttp_init(void)
00081 {
00082
00083 if (irttp == NULL) {
00084 irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL);
00085 if (irttp == NULL)
00086 return -ENOMEM;
00087 }
00088 memset(irttp, 0, sizeof(struct irttp_cb));
00089
00090 irttp->magic = TTP_MAGIC;
00091
00092 irttp->tsaps = hashbin_new(HB_LOCAL);
00093 if (!irttp->tsaps) {
00094 ERROR(__FUNCTION__ "(), can't allocate IrTTP hashbin!\n");
00095 return -ENOMEM;
00096 }
00097
00098 return 0;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107 #ifdef MODULE
00108 void irttp_cleanup(void)
00109 {
00110
00111 ASSERT(irttp != NULL, return;);
00112 ASSERT(irttp->magic == TTP_MAGIC, return;);
00113
00114
00115
00116
00117 hashbin_delete(irttp->tsaps, (FREE_FUNC) __irttp_close_tsap);
00118
00119 irttp->magic = 0;
00120
00121
00122 kfree(irttp);
00123
00124 irttp = NULL;
00125 }
00126 #endif
00127
00128
00129
00130
00131
00132
00133 struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
00134 {
00135 struct tsap_cb *self;
00136 struct lsap_cb *lsap;
00137 notify_t ttp_notify;
00138
00139 ASSERT(irttp != NULL, return NULL;);
00140 ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
00141
00142 self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
00143 if (self == NULL) {
00144 IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
00145 return NULL;
00146 }
00147 memset(self, 0, sizeof(struct tsap_cb));
00148 spin_lock_init(&self->lock);
00149
00150 init_timer(&self->todo_timer);
00151
00152
00153 irda_notify_init(&ttp_notify);
00154 ttp_notify.connect_confirm = irttp_connect_confirm;
00155 ttp_notify.connect_indication = irttp_connect_indication;
00156 ttp_notify.disconnect_indication = irttp_disconnect_indication;
00157 ttp_notify.data_indication = irttp_data_indication;
00158 ttp_notify.udata_indication = irttp_udata_indication;
00159 ttp_notify.instance = self;
00160 strncpy(ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
00161
00162 self->magic = TTP_TSAP_MAGIC;
00163 self->connected = FALSE;
00164
00165 skb_queue_head_init(&self->rx_queue);
00166 skb_queue_head_init(&self->tx_queue);
00167 skb_queue_head_init(&self->rx_fragments);
00168
00169
00170
00171 lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
00172 if (lsap == NULL) {
00173 WARNING(__FUNCTION__ "(), unable to allocate LSAP!!\n");
00174 return NULL;
00175 }
00176
00177
00178
00179
00180
00181
00182 self->stsap_sel = lsap->slsap_sel;
00183 IRDA_DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
00184
00185 self->notify = *notify;
00186 self->lsap = lsap;
00187
00188 hashbin_insert(irttp->tsaps, (queue_t *) self, (int) self, NULL);
00189
00190 if (credit > TTP_MAX_QUEUE)
00191 self->initial_credit = TTP_MAX_QUEUE;
00192 else
00193 self->initial_credit = credit;
00194
00195 return self;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205 static void __irttp_close_tsap(struct tsap_cb *self)
00206 {
00207
00208 ASSERT(self != NULL, return;);
00209 ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
00210
00211 irttp_flush_queues(self);
00212
00213 del_timer(&self->todo_timer);
00214
00215 self->connected = FALSE;
00216 self->magic = ~TTP_TSAP_MAGIC;
00217
00218 kfree(self);
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228 int irttp_close_tsap(struct tsap_cb *self)
00229 {
00230 struct tsap_cb *tsap;
00231
00232 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00233
00234 ASSERT(self != NULL, return -1;);
00235 ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
00236
00237
00238 if (self->connected) {
00239
00240 if (!self->disconnect_pend) {
00241 IRDA_DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
00242 irttp_disconnect_request(self, NULL, P_NORMAL);
00243 }
00244 self->close_pend = TRUE;
00245 irttp_start_todo_timer(self, 1*HZ);
00246
00247 return 0;
00248 }
00249
00250 tsap = hashbin_remove(irttp->tsaps, (int) self, NULL);
00251
00252 ASSERT(tsap == self, return -1;);
00253
00254
00255 if (self->lsap) {
00256 irlmp_close_lsap(self->lsap);
00257 self->lsap = NULL;
00258 }
00259
00260 __irttp_close_tsap(self);
00261
00262 return 0;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271 int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb)
00272 {
00273 ASSERT(self != NULL, return -1;);
00274 ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
00275 ASSERT(skb != NULL, return -1;);
00276
00277 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00278
00279
00280 if ((skb->len == 0) || (!self->connected)) {
00281 IRDA_DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
00282 return -1;
00283 }
00284
00285 if (skb->len > self->max_seg_size) {
00286 IRDA_DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
00287 return -1;
00288 }
00289
00290 irlmp_udata_request(self->lsap, skb);
00291 self->stats.tx_packets++;
00292
00293 return 0;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
00303 {
00304 __u8 *frame;
00305
00306
00307 if ((skb->len == 0) || (!self->connected)) {
00308 WARNING(__FUNCTION__ "(), No data, or not connected\n");
00309 return -ENOTCONN;
00310 }
00311
00312
00313
00314
00315
00316 if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
00317 ERROR(__FUNCTION__
00318 "(), SAR disabled, and data is to large for IrLAP!\n");
00319 return -EMSGSIZE;
00320 }
00321
00322
00323
00324
00325
00326 if ((self->tx_max_sdu_size != 0) &&
00327 (self->tx_max_sdu_size != TTP_SAR_UNBOUND) &&
00328 (skb->len > self->tx_max_sdu_size))
00329 {
00330 ERROR(__FUNCTION__ "(), SAR enabled, "
00331 "but data is larger than TxMaxSduSize!\n");
00332 return -EMSGSIZE;
00333 }
00334
00335
00336
00337 if (skb_queue_len(&self->tx_queue) >= TTP_MAX_QUEUE) {
00338
00339
00340
00341 irttp_run_tx_queue(self);
00342
00343 return -ENOBUFS;
00344 }
00345
00346
00347 if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) {
00348
00349 ASSERT(skb_headroom(skb) >= TTP_HEADER, return -1;);
00350 frame = skb_push(skb, TTP_HEADER);
00351 frame[0] = 0x00;
00352
00353 skb_queue_tail(&self->tx_queue, skb);
00354 } else {
00355
00356
00357
00358
00359
00360
00361 irttp_fragment_skb(self, skb);
00362 }
00363
00364
00365 if ((!self->tx_sdu_busy) &&
00366 (skb_queue_len(&self->tx_queue) > TTP_HIGH_THRESHOLD)) {
00367
00368
00369 self->tx_sdu_busy = TRUE;
00370
00371 if (self->notify.flow_indication) {
00372 self->notify.flow_indication(self->notify.instance,
00373 self, FLOW_STOP);
00374 }
00375 }
00376
00377
00378 irttp_run_tx_queue(self);
00379
00380 return 0;
00381 }
00382
00383
00384
00385
00386
00387
00388
00389 static void irttp_run_tx_queue(struct tsap_cb *self)
00390 {
00391 struct sk_buff *skb;
00392 unsigned long flags;
00393 int n;
00394
00395 if (irda_lock(&self->tx_queue_lock) == FALSE)
00396 return;
00397
00398
00399 while ((self->send_credit > 0) &&
00400 (skb = skb_dequeue(&self->tx_queue)))
00401 {
00402
00403
00404
00405
00406 if (irlmp_get_lap_tx_queue_len(self->lsap) > LAP_MAX_QUEUE) {
00407
00408 skb_queue_head(&self->tx_queue, skb);
00409
00410
00411 irttp_start_todo_timer(self, MSECS_TO_JIFFIES(10));
00412
00413 break;
00414 }
00415
00416
00417
00418
00419
00420
00421 spin_lock_irqsave(&self->lock, flags);
00422
00423 n = self->avail_credit;
00424 self->avail_credit = 0;
00425
00426
00427 if (n > 127) {
00428 self->avail_credit = n-127;
00429 n = 127;
00430 }
00431 self->remote_credit += n;
00432 self->send_credit--;
00433
00434 spin_unlock_irqrestore(&self->lock, flags);
00435
00436
00437
00438
00439
00440 skb->data[0] |= (n & 0x7f);
00441
00442 irlmp_data_request(self->lsap, skb);
00443 self->stats.tx_packets++;
00444
00445
00446 if ((self->tx_sdu_busy) &&
00447 (skb_queue_len(&self->tx_queue) < TTP_LOW_THRESHOLD))
00448 {
00449 self->tx_sdu_busy = FALSE;
00450
00451 if (self->notify.flow_indication)
00452 self->notify.flow_indication(
00453 self->notify.instance, self,
00454 FLOW_START);
00455 }
00456 }
00457 self->tx_queue_lock = 0;
00458 }
00459
00460
00461
00462
00463
00464
00465
00466 void irttp_give_credit(struct tsap_cb *self)
00467 {
00468 struct sk_buff *tx_skb = NULL;
00469 unsigned long flags;
00470 int n;
00471
00472 ASSERT(self != NULL, return;);
00473 ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
00474
00475 IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
00476 self->send_credit, self->avail_credit, self->remote_credit);
00477
00478
00479 tx_skb = dev_alloc_skb(64);
00480 if (!tx_skb)
00481 return;
00482
00483
00484 skb_reserve(tx_skb, self->max_header_size);
00485
00486
00487
00488
00489
00490
00491 spin_lock_irqsave(&self->lock, flags);
00492
00493 n = self->avail_credit;
00494 self->avail_credit = 0;
00495
00496
00497 if (n > 127) {
00498 self->avail_credit = n - 127;
00499 n = 127;
00500 }
00501 self->remote_credit += n;
00502
00503 spin_unlock_irqrestore(&self->lock, flags);
00504
00505 skb_put(tx_skb, 1);
00506 tx_skb->data[0] = (__u8) (n & 0x7f);
00507
00508 irlmp_data_request(self->lsap, tx_skb);
00509 self->stats.tx_packets++;
00510 }
00511
00512
00513
00514
00515
00516
00517
00518 static int irttp_udata_indication(void *instance, void *sap,
00519 struct sk_buff *skb)
00520 {
00521 struct tsap_cb *self;
00522
00523 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00524
00525 self = (struct tsap_cb *) instance;
00526
00527 ASSERT(self != NULL, return -1;);
00528 ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
00529 ASSERT(skb != NULL, return -1;);
00530
00531
00532 if (self->notify.udata_indication)
00533 self->notify.udata_indication(self->notify.instance, self,skb);
00534 else
00535 dev_kfree_skb(skb);
00536
00537 self->stats.rx_packets++;
00538
00539 return 0;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548 static int irttp_data_indication(void *instance, void *sap,
00549 struct sk_buff *skb)
00550 {
00551 struct tsap_cb *self;
00552 int n;
00553
00554 self = (struct tsap_cb *) instance;
00555
00556 n = skb->data[0] & 0x7f;
00557
00558 self->stats.rx_packets++;
00559
00560
00561
00562
00563
00564 if (skb->len > 1) {
00565
00566 self->send_credit += n;
00567 self->remote_credit--;
00568
00569
00570
00571
00572
00573 skb_queue_tail(&self->rx_queue, skb);
00574 } else {
00575 self->send_credit += n;
00576 dev_kfree_skb(skb);
00577 }
00578
00579 irttp_run_rx_queue(self);
00580
00581
00582
00583
00584 if ((skb_queue_empty(&self->tx_queue)) &&
00585 (self->remote_credit < TTP_LOW_THRESHOLD) &&
00586 (self->avail_credit > 0))
00587 {
00588
00589 irttp_start_todo_timer(self, 0);
00590
00591 }
00592
00593
00594
00595
00596
00597 if (self->send_credit == n) {
00598
00599 irttp_start_todo_timer(self, 0);
00600 }
00601 return 0;
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611 void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
00612 {
00613 IRDA_DEBUG(1, __FUNCTION__ "()\n");
00614
00615 ASSERT(self != NULL, return;);
00616 ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
00617
00618 switch (flow) {
00619 case FLOW_STOP:
00620 IRDA_DEBUG(1, __FUNCTION__ "(), flow stop\n");
00621 self->rx_sdu_busy = TRUE;
00622 break;
00623 case FLOW_START:
00624 IRDA_DEBUG(1, __FUNCTION__ "(), flow start\n");
00625 self->rx_sdu_busy = FALSE;
00626
00627 irttp_run_rx_queue(self);
00628 break;
00629 default:
00630 IRDA_DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
00631 }
00632 }
00633
00634
00635
00636
00637
00638
00639
00640 int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
00641 __u32 saddr, __u32 daddr,
00642 struct qos_info *qos, __u32 max_sdu_size,
00643 struct sk_buff *userdata)
00644 {
00645 struct sk_buff *skb;
00646 __u8 *frame;
00647 __u8 n;
00648
00649 IRDA_DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size);
00650
00651 ASSERT(self != NULL, return -EBADR;);
00652 ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
00653
00654 if (self->connected)
00655 return -EISCONN;
00656
00657
00658 if (userdata == NULL) {
00659 skb = dev_alloc_skb(64);
00660 if (!skb)
00661 return -ENOMEM;
00662
00663
00664 skb_reserve(skb, TTP_MAX_HEADER);
00665 } else {
00666 skb = userdata;
00667
00668
00669
00670
00671 ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER, return -1;);
00672 }
00673
00674
00675 self->connected = FALSE;
00676 self->avail_credit = 0;
00677 self->rx_max_sdu_size = max_sdu_size;
00678 self->rx_sdu_size = 0;
00679 self->rx_sdu_busy = FALSE;
00680 self->dtsap_sel = dtsap_sel;
00681
00682 n = self->initial_credit;
00683
00684 self->remote_credit = 0;
00685 self->send_credit = 0;
00686
00687
00688
00689
00690 if (n > 127) {
00691 self->avail_credit=n-127;
00692 n = 127;
00693 }
00694
00695 self->remote_credit = n;
00696
00697
00698 if (max_sdu_size > 0) {
00699 ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
00700 return -1;);
00701
00702
00703 frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
00704
00705 frame[0] = TTP_PARAMETERS | n;
00706 frame[1] = 0x04;
00707 frame[2] = 0x01;
00708 frame[3] = 0x02;
00709
00710 put_unaligned(cpu_to_be16((__u16) max_sdu_size),
00711 (__u16 *)(frame+4));
00712 } else {
00713
00714 frame = skb_push(skb, TTP_HEADER);
00715
00716
00717 frame[0] = n & 0x7f;
00718 }
00719
00720
00721 return irlmp_connect_request(self->lsap, dtsap_sel, saddr, daddr, qos,
00722 skb);
00723 }
00724
00725
00726
00727
00728
00729
00730
00731 static void irttp_connect_confirm(void *instance, void *sap,
00732 struct qos_info *qos, __u32 max_seg_size,
00733 __u8 max_header_size, struct sk_buff *skb)
00734 {
00735 struct tsap_cb *self;
00736 int parameters;
00737 int ret;
00738 __u8 plen;
00739 __u8 n;
00740
00741 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00742
00743 self = (struct tsap_cb *) instance;
00744
00745 ASSERT(self != NULL, return;);
00746 ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
00747 ASSERT(skb != NULL, return;);
00748
00749 self->max_seg_size = max_seg_size - TTP_HEADER;
00750 self->max_header_size = max_header_size + TTP_HEADER;
00751
00752
00753
00754
00755
00756 if (qos) {
00757 IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n",
00758 qos->baud_rate.bits);
00759 IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n",
00760 qos->baud_rate.value);
00761 }
00762
00763 n = skb->data[0] & 0x7f;
00764
00765 IRDA_DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
00766
00767 self->send_credit = n;
00768 self->tx_max_sdu_size = 0;
00769 self->connected = TRUE;
00770
00771 parameters = skb->data[0] & 0x80;
00772
00773 ASSERT(skb->len >= TTP_HEADER, return;);
00774 skb_pull(skb, TTP_HEADER);
00775
00776 if (parameters) {
00777 plen = skb->data[0];
00778
00779 ret = irda_param_extract_all(self, skb->data+1,
00780 IRDA_MIN(skb->len-1, plen),
00781 ¶m_info);
00782
00783
00784 if (ret < 0) {
00785 WARNING(__FUNCTION__
00786 "(), error extracting parameters\n");
00787 dev_kfree_skb(skb);
00788
00789
00790 return;
00791 }
00792
00793 skb_pull(skb, IRDA_MIN(skb->len, plen+1));
00794 }
00795
00796 IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
00797 self->send_credit, self->avail_credit, self->remote_credit);
00798
00799 IRDA_DEBUG(2, __FUNCTION__ "(), MaxSduSize=%d\n", self->tx_max_sdu_size);
00800
00801 if (self->notify.connect_confirm) {
00802 self->notify.connect_confirm(self->notify.instance, self, qos,
00803 self->tx_max_sdu_size,
00804 self->max_header_size, skb);
00805 }
00806 }
00807
00808
00809
00810
00811
00812
00813
00814 void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
00815 __u32 max_seg_size, __u8 max_header_size,
00816 struct sk_buff *skb)
00817 {
00818 struct tsap_cb *self;
00819 struct lsap_cb *lsap;
00820 int parameters;
00821 int ret;
00822 __u8 plen;
00823 __u8 n;
00824
00825 self = (struct tsap_cb *) instance;
00826
00827 ASSERT(self != NULL, return;);
00828 ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
00829 ASSERT(skb != NULL, return;);
00830
00831 lsap = (struct lsap_cb *) sap;
00832
00833 self->max_seg_size = max_seg_size - TTP_HEADER;;
00834 self->max_header_size = max_header_size+TTP_HEADER;
00835
00836 IRDA_DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
00837
00838
00839 self->dtsap_sel = lsap->dlsap_sel;
00840
00841 n = skb->data[0] & 0x7f;
00842
00843 self->send_credit = n;
00844 self->tx_max_sdu_size = 0;
00845
00846 parameters = skb->data[0] & 0x80;
00847
00848 ASSERT(skb->len >= TTP_HEADER, return;);
00849 skb_pull(skb, TTP_HEADER);
00850
00851 if (parameters) {
00852 plen = skb->data[0];
00853
00854 ret = irda_param_extract_all(self, skb->data+1,
00855 IRDA_MIN(skb->len-1, plen),
00856 ¶m_info);
00857
00858
00859 if (ret < 0) {
00860 WARNING(__FUNCTION__
00861 "(), error extracting parameters\n");
00862 dev_kfree_skb(skb);
00863
00864
00865 return;
00866 }
00867
00868
00869 skb_pull(skb, IRDA_MIN(skb->len, plen+1));
00870 }
00871
00872 if (self->notify.connect_indication) {
00873 self->notify.connect_indication(self->notify.instance, self,
00874 qos, self->tx_max_sdu_size,
00875 self->max_header_size, skb);
00876 } else
00877 dev_kfree_skb(skb);
00878 }
00879
00880
00881
00882
00883
00884
00885
00886
00887 int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
00888 struct sk_buff *userdata)
00889 {
00890 struct sk_buff *skb;
00891 __u8 *frame;
00892 int ret;
00893 __u8 n;
00894
00895 ASSERT(self != NULL, return -1;);
00896 ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
00897
00898 IRDA_DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n",
00899 self->stsap_sel);
00900
00901
00902 if (userdata == NULL) {
00903 skb = dev_alloc_skb(64);
00904 if (!skb)
00905 return -ENOMEM;
00906
00907
00908 skb_reserve(skb, TTP_MAX_HEADER);
00909 } else {
00910 skb = userdata;
00911
00912
00913
00914
00915 ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return -1;);
00916 }
00917
00918 self->avail_credit = 0;
00919 self->remote_credit = 0;
00920 self->rx_max_sdu_size = max_sdu_size;
00921 self->rx_sdu_size = 0;
00922 self->rx_sdu_busy = FALSE;
00923
00924 n = self->initial_credit;
00925
00926
00927 if (n > 127) {
00928 self->avail_credit = n - 127;
00929 n = 127;
00930 }
00931
00932 self->remote_credit = n;
00933 self->connected = TRUE;
00934
00935
00936 if (max_sdu_size > 0) {
00937 ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER),
00938 return -1;);
00939
00940
00941 frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
00942
00943 frame[0] = TTP_PARAMETERS | n;
00944 frame[1] = 0x04;
00945
00946
00947
00948
00949 frame[2] = 0x01;
00950 frame[3] = 0x02;
00951
00952 put_unaligned(cpu_to_be16((__u16) max_sdu_size),
00953 (__u16 *)(frame+4));
00954 } else {
00955
00956 frame = skb_push(skb, TTP_HEADER);
00957
00958 frame[0] = n & 0x7f;
00959 }
00960
00961 ret = irlmp_connect_response(self->lsap, skb);
00962
00963 return ret;
00964 }
00965
00966
00967
00968
00969
00970
00971
00972 struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
00973 {
00974 struct tsap_cb *new;
00975
00976 IRDA_DEBUG(1, __FUNCTION__ "()\n");
00977
00978 if (!hashbin_find(irttp->tsaps, (int) orig, NULL)) {
00979 IRDA_DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
00980 return NULL;
00981 }
00982 new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
00983 if (!new) {
00984 IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
00985 return NULL;
00986 }
00987
00988 memcpy(new, orig, sizeof(struct tsap_cb));
00989 new->notify.instance = instance;
00990 new->lsap = irlmp_dup(orig->lsap, new);
00991
00992
00993 init_timer(&new->todo_timer);
00994
00995 skb_queue_head_init(&new->rx_queue);
00996 skb_queue_head_init(&new->tx_queue);
00997 skb_queue_head_init(&new->rx_fragments);
00998
00999 hashbin_insert(irttp->tsaps, (queue_t *) new, (int) new, NULL);
01000
01001 return new;
01002 }
01003
01004
01005
01006
01007
01008
01009
01010
01011 int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
01012 int priority)
01013 {
01014 struct sk_buff *skb;
01015 int ret;
01016
01017 ASSERT(self != NULL, return -1;);
01018 ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
01019
01020
01021 if (!self->connected) {
01022 IRDA_DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
01023 return -1;
01024 }
01025
01026
01027 if (self->disconnect_pend) {
01028 IRDA_DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
01029 if (userdata) {
01030 dev_kfree_skb(userdata);
01031 }
01032
01033
01034 irttp_run_rx_queue(self);
01035 return -1;
01036 }
01037
01038
01039
01040
01041 if (skb_queue_len(&self->tx_queue) > 0) {
01042 if (priority == P_HIGH) {
01043 IRDA_DEBUG(1, __FUNCTION__ "High priority!!()\n" );
01044
01045
01046
01047
01048
01049
01050 irttp_flush_queues(self);
01051 } else if (priority == P_NORMAL) {
01052
01053
01054
01055
01056 if (userdata)
01057 self->disconnect_skb = userdata;
01058 else
01059 self->disconnect_skb = NULL;
01060
01061 self->disconnect_pend = TRUE;
01062
01063 irttp_run_tx_queue(self);
01064
01065 irttp_start_todo_timer(self, MSECS_TO_JIFFIES(1000));
01066 return -1;
01067 }
01068 }
01069 IRDA_DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
01070
01071 self->connected = FALSE;
01072
01073 if (!userdata) {
01074 skb = dev_alloc_skb(64);
01075 if (!skb)
01076 return -ENOMEM;
01077
01078
01079
01080
01081 skb_reserve(skb, TTP_MAX_HEADER);
01082
01083 userdata = skb;
01084 }
01085 ret = irlmp_disconnect_request(self->lsap, userdata);
01086
01087 return ret;
01088 }
01089
01090
01091
01092
01093
01094
01095
01096 void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason,
01097 struct sk_buff *skb)
01098 {
01099 struct tsap_cb *self;
01100
01101 IRDA_DEBUG(4, __FUNCTION__ "()\n");
01102
01103 self = (struct tsap_cb *) instance;
01104
01105 ASSERT(self != NULL, return;);
01106 ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
01107
01108 self->connected = FALSE;
01109
01110
01111 if (self->close_pend) {
01112 irttp_close_tsap(self);
01113 return;
01114 }
01115
01116
01117 if (self->disconnect_pend)
01118 return;
01119
01120 if (self->notify.disconnect_indication)
01121 self->notify.disconnect_indication(self->notify.instance, self,
01122 reason, skb);
01123 else
01124 if (skb)
01125 dev_kfree_skb(skb);
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135 void irttp_do_data_indication(struct tsap_cb *self, struct sk_buff *skb)
01136 {
01137 int err;
01138
01139
01140 if (self->close_pend || self->disconnect_pend) {
01141 dev_kfree_skb(skb);
01142 return;
01143 }
01144
01145 err = self->notify.data_indication(self->notify.instance, self, skb);
01146
01147
01148
01149
01150
01151
01152 if (err == -ENOMEM) {
01153 IRDA_DEBUG(0, __FUNCTION__ "() requeueing skb!\n");
01154
01155
01156 self->rx_sdu_busy = TRUE;
01157
01158
01159 skb_push(skb, TTP_HEADER);
01160 skb->data[0] = 0x00;
01161
01162
01163 skb_queue_head(&self->rx_queue, skb);
01164 }
01165 }
01166
01167
01168
01169
01170
01171
01172
01173 void irttp_run_rx_queue(struct tsap_cb *self)
01174 {
01175 struct sk_buff *skb;
01176 int more = 0;
01177
01178 IRDA_DEBUG(2, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
01179 self->send_credit, self->avail_credit, self->remote_credit);
01180
01181 if (irda_lock(&self->rx_queue_lock) == FALSE)
01182 return;
01183
01184
01185
01186
01187 while (!self->rx_sdu_busy && (skb = skb_dequeue(&self->rx_queue))) {
01188 self->avail_credit++;
01189
01190 more = skb->data[0] & 0x80;
01191
01192
01193 skb_pull(skb, TTP_HEADER);
01194
01195
01196 self->rx_sdu_size += skb->len;
01197
01198
01199
01200
01201
01202
01203
01204 if (self->rx_max_sdu_size == TTP_SAR_DISABLE) {
01205 irttp_do_data_indication(self, skb);
01206 self->rx_sdu_size = 0;
01207
01208 continue;
01209 }
01210
01211
01212 if (more) {
01213
01214
01215
01216
01217 if (self->rx_sdu_size <= self->rx_max_sdu_size) {
01218 IRDA_DEBUG(4, __FUNCTION__ "(), queueing frag\n");
01219 skb_queue_tail(&self->rx_fragments, skb);
01220 } else {
01221
01222 dev_kfree_skb(skb);
01223 }
01224 continue;
01225 }
01226
01227
01228
01229 if ((self->rx_sdu_size <= self->rx_max_sdu_size) ||
01230 (self->rx_max_sdu_size == TTP_SAR_UNBOUND))
01231 {
01232
01233
01234
01235
01236
01237
01238 if (!skb_queue_empty(&self->rx_fragments)) {
01239 skb_queue_tail(&self->rx_fragments,
01240 skb);
01241
01242 skb = irttp_reassemble_skb(self);
01243 }
01244
01245
01246 irttp_do_data_indication(self, skb);
01247 } else {
01248 IRDA_DEBUG(1, __FUNCTION__ "(), Truncated frame\n");
01249
01250
01251 dev_kfree_skb(skb);
01252
01253
01254 skb = irttp_reassemble_skb(self);
01255
01256 irttp_do_data_indication(self, skb);
01257 }
01258 self->rx_sdu_size = 0;
01259 }
01260
01261 self->rx_queue_lock = 0;
01262 }
01263
01264
01265
01266
01267
01268
01269 void irttp_flush_queues(struct tsap_cb *self)
01270 {
01271 struct sk_buff* skb;
01272
01273 IRDA_DEBUG(4, __FUNCTION__ "()\n");
01274
01275 ASSERT(self != NULL, return;);
01276 ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
01277
01278
01279 while ((skb = skb_dequeue(&self->tx_queue)) != NULL)
01280 dev_kfree_skb(skb);
01281
01282
01283 while ((skb = skb_dequeue(&self->rx_queue)) != NULL)
01284 dev_kfree_skb(skb);
01285
01286
01287 while ((skb = skb_dequeue(&self->rx_fragments)) != NULL)
01288 dev_kfree_skb(skb);
01289 }
01290
01291
01292
01293
01294
01295
01296
01297
01298 static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
01299 {
01300 struct sk_buff *skb, *frag;
01301 int n = 0;
01302
01303 ASSERT(self != NULL, return NULL;);
01304 ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
01305
01306 IRDA_DEBUG(2, __FUNCTION__ "(), self->rx_sdu_size=%d\n",
01307 self->rx_sdu_size);
01308
01309 skb = dev_alloc_skb(TTP_HEADER + self->rx_sdu_size);
01310 if (!skb)
01311 return NULL;
01312
01313
01314
01315
01316
01317 skb_reserve(skb, TTP_HEADER);
01318 skb_put(skb, self->rx_sdu_size);
01319
01320
01321
01322
01323 while ((frag = skb_dequeue(&self->rx_fragments)) != NULL) {
01324 memcpy(skb->data+n, frag->data, frag->len);
01325 n += frag->len;
01326
01327 dev_kfree_skb(frag);
01328 }
01329 IRDA_DEBUG(2, __FUNCTION__ "(), frame len=%d\n", n);
01330
01331 IRDA_DEBUG(2, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
01332 ASSERT(n <= self->rx_sdu_size, return NULL;);
01333
01334
01335 skb_trim(skb, n);
01336
01337 self->rx_sdu_size = 0;
01338
01339 return skb;
01340 }
01341
01342
01343
01344
01345
01346
01347
01348 static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb)
01349 {
01350 struct sk_buff *frag;
01351 __u8 *frame;
01352
01353 IRDA_DEBUG(2, __FUNCTION__ "()\n");
01354
01355 ASSERT(self != NULL, return;);
01356 ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
01357 ASSERT(skb != NULL, return;);
01358
01359
01360
01361
01362 while (skb->len > self->max_seg_size) {
01363 IRDA_DEBUG(2, __FUNCTION__ "(), fragmenting ...\n");
01364
01365
01366 frag = dev_alloc_skb(self->max_seg_size+self->max_header_size);
01367 if (!frag)
01368 return;
01369
01370 skb_reserve(frag, self->max_header_size);
01371
01372
01373 memcpy(skb_put(frag, self->max_seg_size), skb->data,
01374 self->max_seg_size);
01375
01376
01377 frame = skb_push(frag, TTP_HEADER);
01378 frame[0] = TTP_MORE;
01379
01380
01381 skb_pull(skb, self->max_seg_size);
01382
01383
01384 skb_queue_tail(&self->tx_queue, frag);
01385 }
01386
01387 IRDA_DEBUG(2, __FUNCTION__ "(), queuing last segment\n");
01388
01389 frame = skb_push(skb, TTP_HEADER);
01390 frame[0] = 0x00;
01391
01392
01393 skb_queue_tail(&self->tx_queue, skb);
01394 }
01395
01396
01397
01398
01399
01400
01401
01402
01403 static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
01404 int get)
01405 {
01406 struct tsap_cb *self;
01407
01408 self = (struct tsap_cb *) instance;
01409
01410 ASSERT(self != NULL, return -1;);
01411 ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
01412
01413 if (get)
01414 param->pv.i = self->tx_max_sdu_size;
01415 else
01416 self->tx_max_sdu_size = param->pv.i;
01417
01418 IRDA_DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i);
01419
01420 return 0;
01421 }
01422
01423
01424
01425
01426
01427
01428
01429 static void irttp_todo_expired(unsigned long data)
01430 {
01431 struct tsap_cb *self = (struct tsap_cb *) data;
01432
01433
01434 if (!self || self->magic != TTP_TSAP_MAGIC)
01435 return;
01436
01437 irttp_run_rx_queue(self);
01438 irttp_run_tx_queue(self);
01439
01440
01441 if ((self->remote_credit < TTP_LOW_THRESHOLD) &&
01442 (self->avail_credit > 0) && (skb_queue_empty(&self->tx_queue)))
01443 {
01444 irttp_give_credit(self);
01445 }
01446
01447
01448 if (self->disconnect_pend) {
01449
01450 if (skb_queue_empty(&self->tx_queue)) {
01451
01452
01453 self->disconnect_pend = FALSE;
01454 if (self->disconnect_skb) {
01455 irttp_disconnect_request(
01456 self, self->disconnect_skb, P_NORMAL);
01457 self->disconnect_skb = NULL;
01458 } else
01459 irttp_disconnect_request(self, NULL,