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/module.h>
00028
00029 #include <linux/kernel.h>
00030 #include <linux/string.h>
00031 #include <linux/init.h>
00032 #include <linux/errno.h>
00033 #include <linux/proc_fs.h>
00034 #include <linux/netdevice.h>
00035 #include <linux/etherdevice.h>
00036
00037 #include <asm/system.h>
00038 #include <asm/bitops.h>
00039 #include <asm/byteorder.h>
00040
00041 #include <net/irda/irda.h>
00042 #include <net/irda/irttp.h>
00043 #include <net/irda/irlmp.h>
00044 #include <net/irda/iriap.h>
00045 #include <net/irda/timer.h>
00046
00047 #include <net/irda/irlan_common.h>
00048 #include <net/irda/irlan_client.h>
00049 #include <net/irda/irlan_provider.h>
00050 #include <net/irda/irlan_eth.h>
00051 #include <net/irda/irlan_filter.h>
00052
00053
00054
00055
00056
00057
00058 #undef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
00059
00060
00061
00062
00063
00064
00065 hashbin_t *irlan = NULL;
00066 static __u32 ckey, skey;
00067
00068
00069 static int eth = 0;
00070 static int access = ACCESS_PEER;
00071
00072 static char *irlan_state[] = {
00073 "IRLAN_IDLE",
00074 "IRLAN_QUERY",
00075 "IRLAN_CONN",
00076 "IRLAN_INFO",
00077 "IRLAN_MEDIA",
00078 "IRLAN_OPEN",
00079 "IRLAN_WAIT",
00080 "IRLAN_ARB",
00081 "IRLAN_DATA",
00082 "IRLAN_CLOSE",
00083 "IRLAN_SYNC"
00084 };
00085
00086 static char *irlan_access[] = {
00087 "UNKNOWN",
00088 "DIRECT",
00089 "PEER",
00090 "HOSTED"
00091 };
00092
00093 static char *irlan_media[] = {
00094 "UNKNOWN",
00095 "802.3",
00096 "802.5"
00097 };
00098
00099 static void __irlan_close(struct irlan_cb *self);
00100 static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
00101 __u8 value_byte, __u16 value_short,
00102 __u8 *value_array, __u16 value_len);
00103 void irlan_close_tsaps(struct irlan_cb *self);
00104
00105 #ifdef CONFIG_PROC_FS
00106 static int irlan_proc_read(char *buf, char **start, off_t offset, int len,
00107 int unused);
00108
00109 extern struct proc_dir_entry *proc_irda;
00110 #endif
00111
00112
00113
00114
00115
00116
00117
00118 int __init irlan_init(void)
00119 {
00120 struct irlan_cb *new;
00121 __u16 hints;
00122
00123 IRDA_DEBUG(4, __FUNCTION__"()\n");
00124
00125
00126 irlan = hashbin_new(HB_LOCAL);
00127 if (irlan == NULL) {
00128 printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
00129 return -ENOMEM;
00130 }
00131 #ifdef CONFIG_PROC_FS
00132 create_proc_entry("irlan", 0, proc_irda)->get_info = irlan_proc_read;
00133 #endif
00134
00135 hints = irlmp_service_to_hint(S_LAN);
00136
00137
00138 ckey = irlmp_register_client(hints, irlan_client_discovery_indication,
00139 NULL);
00140
00141
00142 skey = irlmp_register_service(hints);
00143
00144
00145 new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY);
00146
00147
00148 irlan_provider_open_ctrl_tsap(new);
00149
00150
00151 irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
00152
00153 return 0;
00154 }
00155
00156 void irlan_cleanup(void)
00157 {
00158 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00159
00160 irlmp_unregister_client(ckey);
00161 irlmp_unregister_service(skey);
00162
00163 #ifdef CONFIG_PROC_FS
00164 remove_proc_entry("irlan", proc_irda);
00165 #endif
00166
00167
00168
00169 hashbin_delete(irlan, (FREE_FUNC) __irlan_close);
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 int irlan_register_netdev(struct irlan_cb *self)
00179 {
00180 int i=0;
00181
00182 IRDA_DEBUG(0, __FUNCTION__ "()\n");
00183
00184
00185 if (!eth) {
00186
00187 do {
00188 sprintf(self->ifname, "%s%d", "irlan", i++);
00189 } while (dev_get(self->ifname));
00190 }
00191 self->dev.name = self->ifname;
00192
00193 if (register_netdev(&self->dev) != 0) {
00194 IRDA_DEBUG(2, __FUNCTION__ "(), register_netdev() failed!\n");
00195 return -1;
00196 }
00197 return 0;
00198 }
00199
00200
00201
00202
00203
00204
00205
00206 struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
00207 {
00208 struct irlan_cb *self;
00209
00210 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00211
00212
00213
00214
00215 self = kmalloc(sizeof(struct irlan_cb), GFP_ATOMIC);
00216 if (self == NULL)
00217 return NULL;
00218
00219 memset(self, 0, sizeof(struct irlan_cb));
00220
00221
00222
00223
00224 self->magic = IRLAN_MAGIC;
00225
00226 ASSERT(irlan != NULL, return NULL;);
00227
00228 sprintf(self->ifname, "%s", "unknown");
00229
00230 self->dev.priv = (void *) self;
00231 self->dev.next = NULL;
00232 self->dev.init = irlan_eth_init;
00233
00234 self->saddr = saddr;
00235 self->daddr = daddr;
00236
00237
00238 self->provider.access_type = access;
00239 self->media = MEDIA_802_3;
00240
00241 init_timer(&self->watchdog_timer);
00242 init_timer(&self->client.kick_timer);
00243
00244 hashbin_insert(irlan, (queue_t *) self, daddr, NULL);
00245
00246 skb_queue_head_init(&self->client.txq);
00247
00248 irlan_next_client_state(self, IRLAN_IDLE);
00249 irlan_next_provider_state(self, IRLAN_IDLE);
00250
00251 irlan_register_netdev(self);
00252
00253 return self;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262 static void __irlan_close(struct irlan_cb *self)
00263 {
00264 struct sk_buff *skb;
00265
00266 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00267
00268 ASSERT(self != NULL, return;);
00269 ASSERT(self->magic == IRLAN_MAGIC, return;);
00270
00271 del_timer(&self->watchdog_timer);
00272 del_timer(&self->client.kick_timer);
00273
00274
00275 irlan_close_tsaps(self);
00276
00277 if (self->client.iriap)
00278 iriap_close(self->client.iriap);
00279
00280
00281 while ((skb = skb_dequeue(&self->client.txq)))
00282 dev_kfree_skb(skb);
00283
00284 unregister_netdev(&self->dev);
00285
00286 self->magic = 0;
00287 kfree(self);
00288 }
00289
00290
00291
00292
00293
00294
00295
00296 void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
00297 __u32 max_sdu_size, __u8 max_header_size,
00298 struct sk_buff *skb)
00299 {
00300 struct irlan_cb *self;
00301 struct tsap_cb *tsap;
00302
00303 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00304
00305 self = (struct irlan_cb *) instance;
00306 tsap = (struct tsap_cb *) sap;
00307
00308 ASSERT(self != NULL, return;);
00309 ASSERT(self->magic == IRLAN_MAGIC, return;);
00310 ASSERT(tsap == self->tsap_data,return;);
00311
00312 self->max_sdu_size = max_sdu_size;
00313 self->max_header_size = max_header_size;
00314
00315 IRDA_DEBUG(0, "IrLAN, We are now connected!\n");
00316
00317 del_timer(&self->watchdog_timer);
00318
00319 irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
00320 irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
00321
00322 if (self->provider.access_type == ACCESS_PEER) {
00323
00324
00325
00326
00327 irlan_get_unicast_addr(self);
00328 irlan_open_unicast_addr(self);
00329 }
00330
00331 self->dev.tbusy = 0;
00332 self->disconnect_reason = 0;
00333 }
00334
00335 void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos,
00336 __u32 max_sdu_size, __u8 max_header_size,
00337 struct sk_buff *skb)
00338 {
00339 struct irlan_cb *self;
00340
00341 self = (struct irlan_cb *) instance;
00342
00343 ASSERT(self != NULL, return;);
00344 ASSERT(self->magic == IRLAN_MAGIC, return;);
00345
00346 self->max_sdu_size = max_sdu_size;
00347 self->max_header_size = max_header_size;
00348
00349
00350
00351 IRDA_DEBUG(2, "IrLAN, We are now connected!\n");
00352 del_timer(&self->watchdog_timer);
00353
00354
00355
00356
00357
00358 irlan_get_unicast_addr(self);
00359 irlan_open_unicast_addr(self);
00360
00361
00362 irlan_set_broadcast_filter(self, TRUE);
00363 irlan_set_multicast_filter(self, TRUE);
00364
00365
00366 self->dev.tbusy = 0;
00367 self->dev.start = 1;
00368 self->disconnect_reason = 0;
00369
00370 #ifdef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
00371 irlan_eth_send_gratuitous_arp(&self->dev);
00372 #endif
00373 }
00374
00375
00376
00377
00378
00379
00380
00381 void irlan_disconnect_indication(void *instance, void *sap, LM_REASON reason,
00382 struct sk_buff *userdata)
00383 {
00384 struct irlan_cb *self;
00385 struct tsap_cb *tsap;
00386
00387 IRDA_DEBUG(0, __FUNCTION__ "(), reason=%d\n", reason);
00388
00389 self = (struct irlan_cb *) instance;
00390 tsap = (struct tsap_cb *) sap;
00391
00392 ASSERT(self != NULL, return;);
00393 ASSERT(self->magic == IRLAN_MAGIC, return;);
00394 ASSERT(tsap != NULL, return;);
00395 ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
00396
00397 ASSERT(tsap == self->tsap_data, return;);
00398
00399 IRDA_DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
00400
00401
00402 self->disconnect_reason = reason;
00403
00404 switch (reason) {
00405 case LM_USER_REQUEST:
00406 IRDA_DEBUG(2, __FUNCTION__ "(), user request\n");
00407 break;
00408 case LM_LAP_DISCONNECT:
00409 IRDA_DEBUG(2, __FUNCTION__ "(), Unexpected IrLAP disconnect\n");
00410 break;
00411 case LM_CONNECT_FAILURE:
00412 IRDA_DEBUG(2, __FUNCTION__ "(), IrLAP connect failed\n");
00413 break;
00414 case LM_LAP_RESET:
00415 IRDA_DEBUG(2, __FUNCTION__ "(), IrLAP reset\n");
00416 break;
00417 case LM_INIT_DISCONNECT:
00418 IRDA_DEBUG(2, __FUNCTION__ "(), IrLMP connect failed\n");
00419 break;
00420 default:
00421 ERROR(__FUNCTION__ "(), Unknown disconnect reason\n");
00422 break;
00423 }
00424 irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
00425 irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
00426 }
00427
00428 void irlan_open_data_tsap(struct irlan_cb *self)
00429 {
00430 struct tsap_cb *tsap;
00431 notify_t notify;
00432
00433 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00434
00435 ASSERT(self != NULL, return;);
00436 ASSERT(self->magic == IRLAN_MAGIC, return;);
00437
00438
00439 if (self->tsap_data)
00440 return;
00441
00442 irda_notify_init(¬ify);
00443
00444 notify.data_indication = irlan_eth_receive;
00445 notify.udata_indication = irlan_eth_receive;
00446 notify.connect_indication = irlan_connect_indication;
00447 notify.connect_confirm = irlan_connect_confirm;
00448
00449 notify.disconnect_indication = irlan_disconnect_indication;
00450 notify.instance = self;
00451 strncpy(notify.name, "IrLAN data", NOTIFY_MAX_NAME);
00452
00453 tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, ¬ify);
00454 if (!tsap) {
00455 IRDA_DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
00456 return;
00457 }
00458 self->tsap_data = tsap;
00459
00460
00461
00462
00463
00464 self->stsap_sel_data = self->tsap_data->stsap_sel;
00465 }
00466
00467 void irlan_close_tsaps(struct irlan_cb *self)
00468 {
00469 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00470
00471 ASSERT(self != NULL, return;);
00472 ASSERT(self->magic == IRLAN_MAGIC, return;);
00473
00474
00475 if (self->tsap_data) {
00476 irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);
00477 irttp_close_tsap(self->tsap_data);
00478 self->tsap_data = NULL;
00479 }
00480 if (self->client.tsap_ctrl) {
00481 irttp_disconnect_request(self->client.tsap_ctrl, NULL,
00482 P_NORMAL);
00483 irttp_close_tsap(self->client.tsap_ctrl);
00484 self->client.tsap_ctrl = NULL;
00485 }
00486 if (self->provider.tsap_ctrl) {
00487 irttp_disconnect_request(self->provider.tsap_ctrl, NULL,
00488 P_NORMAL);
00489 irttp_close_tsap(self->provider.tsap_ctrl);
00490 self->provider.tsap_ctrl = NULL;
00491 }
00492 }
00493
00494
00495
00496
00497
00498
00499
00500 void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel)
00501 {
00502 struct ias_object *obj;
00503 struct ias_value *new_value;
00504
00505 ASSERT(self != NULL, return;);
00506 ASSERT(self->magic == IRLAN_MAGIC, return;);
00507
00508
00509
00510
00511
00512 if (!irias_find_object("IrLAN")) {
00513 obj = irias_new_object("IrLAN", IAS_IRLAN_ID);
00514 irias_add_integer_attrib(obj, "IrDA:TinyTP:LsapSel", tsap_sel);
00515 irias_insert_object(obj);
00516 } else {
00517 new_value = irias_new_integer_value(tsap_sel);
00518 irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
00519 new_value);
00520 }
00521
00522
00523 if (!irias_find_object("PnP")) {
00524 obj = irias_new_object("PnP", IAS_PNP_ID);
00525 #if 0
00526 irias_add_string_attrib(obj, "Name", sysctl_devname);
00527 #else
00528 irias_add_string_attrib(obj, "Name", "Linux");
00529 #endif
00530 irias_add_string_attrib(obj, "DeviceID", "HWP19F0");
00531 irias_add_integer_attrib(obj, "CompCnt", 1);
00532 if (self->provider.access_type == ACCESS_PEER)
00533 irias_add_string_attrib(obj, "Comp#01", "PNP8389");
00534 else
00535 irias_add_string_attrib(obj, "Comp#01", "PNP8294");
00536
00537 irias_add_string_attrib(obj, "Manufacturer", "Linux-IrDA Project");
00538 irias_insert_object(obj);
00539 }
00540 }
00541
00542
00543
00544
00545
00546
00547
00548 int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
00549 {
00550 struct sk_buff *skb;
00551
00552 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00553
00554 if (irda_lock(&self->client.tx_busy) == FALSE)
00555 return -EBUSY;
00556
00557 skb = skb_dequeue(&self->client.txq);
00558 if (!skb) {
00559 self->client.tx_busy = FALSE;
00560 return 0;
00561 }
00562
00563
00564 if ((self->client.tsap_ctrl == NULL) ||
00565 (self->client.state == IRLAN_IDLE))
00566 {
00567 self->client.tx_busy = FALSE;
00568 dev_kfree_skb(skb);
00569 return -1;
00570 }
00571 IRDA_DEBUG(2, __FUNCTION__ "(), sending ...\n");
00572
00573 return irttp_data_request(self->client.tsap_ctrl, skb);
00574 }
00575
00576
00577
00578
00579
00580
00581
00582 void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb)
00583 {
00584 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00585
00586
00587 skb_queue_tail(&self->client.txq, skb);
00588
00589
00590 irlan_run_ctrl_tx_queue(self);
00591 }
00592
00593
00594
00595
00596
00597
00598
00599 void irlan_get_provider_info(struct irlan_cb *self)
00600 {
00601 struct sk_buff *skb;
00602 __u8 *frame;
00603
00604 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00605
00606 ASSERT(self != NULL, return;);
00607 ASSERT(self->magic == IRLAN_MAGIC, return;);
00608
00609 skb = dev_alloc_skb(64);
00610 if (!skb)
00611 return;
00612
00613
00614 skb_reserve(skb, self->client.max_header_size);
00615 skb_put(skb, 2);
00616
00617 frame = skb->data;
00618
00619 frame[0] = CMD_GET_PROVIDER_INFO;
00620 frame[1] = 0x00;
00621
00622 irlan_ctrl_data_request(self, skb);
00623 }
00624
00625
00626
00627
00628
00629
00630
00631 void irlan_open_data_channel(struct irlan_cb *self)
00632 {
00633 struct sk_buff *skb;
00634 __u8 *frame;
00635
00636 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00637
00638 ASSERT(self != NULL, return;);
00639 ASSERT(self->magic == IRLAN_MAGIC, return;);
00640
00641 skb = dev_alloc_skb(64);
00642 if (!skb)
00643 return;
00644
00645 skb_reserve(skb, self->client.max_header_size);
00646 skb_put(skb, 2);
00647
00648 frame = skb->data;
00649
00650
00651 frame[0] = CMD_OPEN_DATA_CHANNEL;
00652 frame[1] = 0x02;
00653
00654 irlan_insert_string_param(skb, "MEDIA", "802.3");
00655 irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
00656
00657
00658
00659
00660 irlan_ctrl_data_request(self, skb);
00661 }
00662
00663 void irlan_close_data_channel(struct irlan_cb *self)
00664 {
00665 struct sk_buff *skb;
00666 __u8 *frame;
00667
00668 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00669
00670 ASSERT(self != NULL, return;);
00671 ASSERT(self->magic == IRLAN_MAGIC, return;);
00672
00673
00674 if (self->client.tsap_ctrl == NULL)
00675 return;
00676
00677 skb = dev_alloc_skb(64);
00678 if (!skb)
00679 return;
00680
00681 skb_reserve(skb, self->client.max_header_size);
00682 skb_put(skb, 2);
00683
00684 frame = skb->data;
00685
00686
00687 frame[0] = CMD_CLOSE_DATA_CHAN;
00688 frame[1] = 0x01;
00689
00690 irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
00691
00692 irlan_ctrl_data_request(self, skb);
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702 void irlan_open_unicast_addr(struct irlan_cb *self)
00703 {
00704 struct sk_buff *skb;
00705 __u8 *frame;
00706
00707 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00708
00709 ASSERT(self != NULL, return;);
00710 ASSERT(self->magic == IRLAN_MAGIC, return;);
00711
00712 skb = dev_alloc_skb(128);
00713 if (!skb)
00714 return;
00715
00716
00717 skb_reserve(skb, self->max_header_size);
00718 skb_put(skb, 2);
00719
00720 frame = skb->data;
00721
00722 frame[0] = CMD_FILTER_OPERATION;
00723 frame[1] = 0x03;
00724 irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
00725 irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
00726 irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
00727
00728 irlan_ctrl_data_request(self, skb);
00729 }
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740 void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
00741 {
00742 struct sk_buff *skb;
00743 __u8 *frame;
00744
00745 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00746
00747 ASSERT(self != NULL, return;);
00748 ASSERT(self->magic == IRLAN_MAGIC, return;);
00749
00750 skb = dev_alloc_skb(128);
00751 if (!skb)
00752 return;
00753
00754
00755 skb_reserve(skb, self->client.max_header_size);
00756 skb_put(skb, 2);
00757
00758 frame = skb->data;
00759
00760 frame[0] = CMD_FILTER_OPERATION;
00761 frame[1] = 0x03;
00762 irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
00763 irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
00764 if (status)
00765 irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
00766 else
00767 irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
00768
00769 irlan_ctrl_data_request(self, skb);
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779 void irlan_set_multicast_filter(struct irlan_cb *self, int status)
00780 {
00781 struct sk_buff *skb;
00782 __u8 *frame;
00783
00784 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00785
00786 ASSERT(self != NULL, return;);
00787 ASSERT(self->magic == IRLAN_MAGIC, return;);
00788
00789 skb = dev_alloc_skb(128);
00790 if (!skb)
00791 return;
00792
00793
00794 skb_reserve(skb, self->client.max_header_size);
00795 skb_put(skb, 2);
00796
00797 frame = skb->data;
00798
00799 frame[0] = CMD_FILTER_OPERATION;
00800 frame[1] = 0x03;
00801 irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
00802 irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
00803 if (status)
00804 irlan_insert_string_param(skb, "FILTER_MODE", "ALL");
00805 else
00806 irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
00807
00808 irlan_ctrl_data_request(self, skb);
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 void irlan_get_unicast_addr(struct irlan_cb *self)
00820 {
00821 struct sk_buff *skb;
00822 __u8 *frame;
00823
00824 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00825
00826 ASSERT(self != NULL, return;);
00827 ASSERT(self->magic == IRLAN_MAGIC, return;);
00828
00829 skb = dev_alloc_skb(128);
00830 if (!skb)
00831 return;
00832
00833
00834 skb_reserve(skb, self->client.max_header_size);
00835 skb_put(skb, 2);
00836
00837 frame = skb->data;
00838
00839 frame[0] = CMD_FILTER_OPERATION;
00840 frame[1] = 0x03;
00841 irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
00842 irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
00843 irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC");
00844
00845 irlan_ctrl_data_request(self, skb);
00846 }
00847
00848
00849
00850
00851
00852
00853
00854 void irlan_get_media_char(struct irlan_cb *self)
00855 {
00856 struct sk_buff *skb;
00857 __u8 *frame;
00858
00859 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00860
00861 ASSERT(self != NULL, return;);
00862 ASSERT(self->magic == IRLAN_MAGIC, return;);
00863
00864 skb = dev_alloc_skb(64);
00865 if (!skb)
00866 return;
00867
00868
00869 skb_reserve(skb, self->client.max_header_size);
00870 skb_put(skb, 2);
00871
00872 frame = skb->data;
00873
00874
00875 frame[0] = CMD_GET_MEDIA_CHAR;
00876 frame[1] = 0x01;
00877
00878 irlan_insert_string_param(skb, "MEDIA", "802.3");
00879
00880 irlan_ctrl_data_request(self, skb);
00881 }
00882
00883
00884
00885
00886
00887
00888
00889 int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value)
00890 {
00891 return __irlan_insert_param(skb, param, IRLAN_BYTE, value, 0, NULL, 0);
00892 }
00893
00894 int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value)
00895 {
00896 return __irlan_insert_param(skb, param, IRLAN_SHORT, 0, value, NULL, 0);
00897 }
00898
00899
00900
00901
00902
00903
00904
00905 int irlan_insert_string_param(struct sk_buff *skb, char *param, char *string)
00906 {
00907 int string_len = strlen(string);
00908
00909 return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string,
00910 string_len);
00911 }
00912
00913
00914
00915
00916
00917
00918
00919 int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array,
00920 __u16 array_len)
00921 {
00922 return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array,
00923 array_len);
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
00936 __u8 value_byte, __u16 value_short,
00937 __u8 *value_array, __u16 value_len)
00938 {
00939 __u8 *frame;
00940 __u8 param_len;
00941 __u16 tmp_le;
00942 int n=0;
00943
00944 if (skb == NULL) {
00945 IRDA_DEBUG(2, __FUNCTION__ "(), Got NULL skb\n");
00946 return 0;
00947 }
00948
00949 param_len = strlen(param);
00950 switch (type) {
00951 case IRLAN_BYTE:
00952 value_len = 1;
00953 break;
00954 case IRLAN_SHORT:
00955 value_len = 2;
00956 break;
00957 case IRLAN_ARRAY:
00958 ASSERT(value_array != NULL, return 0;);
00959 ASSERT(value_len > 0, return 0;);
00960 break;
00961 default:
00962 IRDA_DEBUG(2, __FUNCTION__ "(), Unknown parameter type!\n");
00963 return 0;
00964 break;
00965 }
00966
00967
00968 frame = skb->tail;
00969
00970
00971 if (skb_tailroom(skb) < (param_len+value_len+3)) {
00972 IRDA_DEBUG(2, __FUNCTION__ "(), No more space at end of skb\n");
00973 return 0;
00974 }
00975 skb_put(skb, param_len+value_len+3);
00976
00977
00978 frame[n++] = param_len;
00979
00980
00981 memcpy(frame+n, param, param_len); n += param_len;
00982
00983
00984 tmp_le = cpu_to_le16(value_len);
00985 memcpy(frame+n, &tmp_le, 2); n += 2;
00986
00987
00988 switch (type) {
00989 case IRLAN_BYTE:
00990 frame[n++] = value_byte;
00991 break;
00992 case IRLAN_SHORT:
00993 tmp_le = cpu_to_le16(value_short);
00994 memcpy(frame+n, &tmp_le, 2); n += 2;
00995 break;
00996 case IRLAN_ARRAY:
00997 memcpy(frame+n, value_array, value_len); n+=value_len;
00998 break;
00999 default:
01000 break;
01001 }
01002 ASSERT(n == (param_len+value_len+3), return 0;);
01003
01004 return param_len+value_len+3;
01005 }
01006
01007
01008
01009
01010
01011
01012
01013 int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
01014 {
01015 __u8 name_len;
01016 __u16 val_len;
01017 int n=0;
01018
01019 IRDA_DEBUG(4, __FUNCTION__ "()\n");
01020
01021
01022 name_len = buf[n++];
01023
01024 if (name_len > 254) {
01025 IRDA_DEBUG(2, __FUNCTION__ "(), name_len > 254\n");
01026 return -RSP_INVALID_COMMAND_FORMAT;
01027 }
01028
01029
01030 memcpy(name, buf+n, name_len);
01031 name[name_len] = '\0';
01032 n+=name_len;
01033
01034
01035
01036
01037
01038 memcpy(&val_len, buf+n, 2);
01039 le16_to_cpus(&val_len); n+=2;
01040
01041 if (val_len > 1016) {
01042 IRDA_DEBUG(2, __FUNCTION__ "(), parameter length to long\n");
01043 return -RSP_INVALID_COMMAND_FORMAT;
01044 }
01045 *len = val_len;
01046
01047
01048 memcpy(value, buf+n, val_len);
01049 value[val_len] = '\0';
01050 n+=val_len;
01051
01052 IRDA_DEBUG(4, "Parameter: %s ", name);
01053 IRDA_DEBUG(4, "Value: %s\n", value);
01054
01055 return n;
01056 }
01057
01058 #ifdef CONFIG_PROC_FS
01059
01060
01061
01062
01063
01064 static int irlan_proc_read(char *buf, char **start, off_t offset, int len,
01065 int unused)
01066 {
01067 struct irlan_cb *self;
01068 unsigned long flags;
01069
01070 save_flags(flags);
01071 cli();
01072
01073 ASSERT(irlan != NULL, return 0;);
01074
01075 len = 0;
01076
01077 len += sprintf(buf+len, "IrLAN instances:\n");
01078
01079 self = (struct irlan_cb *) hashbin_get_first(irlan);
01080 while (self != NULL) {
01081 ASSERT(self->magic == IRLAN_MAGIC, return len;);
01082
01083 len += sprintf(buf+len, "ifname: %s,\n",
01084 self->ifname);
01085 len += sprintf(buf+len, "client state: %s, ",
01086 irlan_state[ self->client.state]);
01087 len += sprintf(buf+len, "provider state: %s,\n",
01088 irlan_state[ self->provider.state]);
01089 len += sprintf(buf+len, "saddr: %#08x, ",
01090 self->saddr);
01091 len += sprintf(buf+len, "daddr: %#08x\n",
01092 self->daddr);
01093 len += sprintf(buf+len, "version: %d.%d,\n",
01094 self->version[1], self->version[0]);
01095 len += sprintf(buf+len, "access type: %s\n",
01096 irlan_access[self->client.access_type]);
01097 len += sprintf(buf+len, "media: %s\n",
01098 irlan_media[self->media]);
01099
01100 len += sprintf(buf+len, "local filter:\n");
01101 len += sprintf(buf+len, "remote filter: ");
01102 len += irlan_print_filter(self->client.filter_type,
01103 buf+len);
01104
01105 len += sprintf(buf+len, "client tx busy: %s\n",
01106 self->client.tx_busy ? "TRUE" : "FALSE");
01107
01108 len += sprintf(buf+len, "dev tx busy: %s\n",
01109 self->dev.tbusy ? "TRUE" : "FALSE");
01110
01111 len += sprintf(buf+len, "\n");
01112
01113 self = (struct irlan_cb *) hashbin_get_next(irlan);
01114 }
01115 restore_flags(flags);
01116
01117 return len;
01118 }
01119 #endif
01120
01121
01122
01123
01124
01125
01126
01127 void print_ret_code(__u8 code)
01128 {
01129 switch(code) {
01130 case 0:
01131 printk(KERN_INFO "Success\n");
01132 break;
01133 case 1:
01134 WARNING("IrLAN: Insufficient resources\n");
01135 break;
01136 case 2:
01137 WARNING("IrLAN: Invalid command format\n");
01138 break;
01139 case 3:
01140 WARNING("IrLAN: Command not supported\n");
01141 break;
01142 case 4:
01143 WARNING("IrLAN: Parameter not supported\n");
01144 break;
01145 case 5:
01146 WARNING("IrLAN: Value not supported\n");
01147 break;
01148 case 6:
01149 WARNING("IrLAN: Not open\n");
01150 break;
01151 case 7:
01152 WARNING("IrLAN: Authentication required\n");
01153 break;
01154 case 8:
01155 WARNING("IrLAN: Invalid password\n");
01156 break;
01157 case 9:
01158 WARNING("IrLAN: Protocol error\n");
01159 break;
01160 case 255:
01161 WARNING("IrLAN: Asynchronous status\n");
01162 break;
01163 }
01164 }
01165
01166 void irlan_mod_inc_use_count(void)
01167 {
01168 #ifdef MODULE
01169 MOD_INC_USE_COUNT;
01170 #endif
01171 }
01172
01173 void irlan_mod_dec_use_count(void)
01174 {
01175 #ifdef MODULE
01176 MOD_DEC_USE_COUNT;
01177 #endif
01178 }
01179
01180 #ifdef MODULE
01181
01182 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
01183 MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
01184
01185 MODULE_PARM(eth, "i");
01186 MODULE_PARM(access, "i");
01187 MODULE_PARM(timeout, "i");
01188
01189
01190
01191
01192
01193
01194
01195 int init_module(void)
01196 {
01197 return irlan_init();
01198 }
01199
01200
01201
01202
01203
01204
01205
01206 void cleanup_module(void)
01207 {
01208
01209 irlan_cleanup();
01210 }
01211
01212 #endif
01213