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/types.h>
00028 #include <linux/skbuff.h>
00029 #include <linux/string.h>
00030 #include <linux/init.h>
00031
00032 #include <asm/byteorder.h>
00033 #include <asm/unaligned.h>
00034
00035 #include <net/irda/irda.h>
00036 #include <net/irda/irttp.h>
00037 #include <net/irda/irmod.h>
00038 #include <net/irda/irlmp.h>
00039 #include <net/irda/irias_object.h>
00040 #include <net/irda/iriap_event.h>
00041 #include <net/irda/iriap.h>
00042
00043
00044 static const char *ias_charset_types[] = {
00045 "CS_ASCII",
00046 "CS_ISO_8859_1",
00047 "CS_ISO_8859_2",
00048 "CS_ISO_8859_3",
00049 "CS_ISO_8859_4",
00050 "CS_ISO_8859_5",
00051 "CS_ISO_8859_6",
00052 "CS_ISO_8859_7",
00053 "CS_ISO_8859_8",
00054 "CS_ISO_8859_9",
00055 "CS_UNICODE"
00056 };
00057
00058 static hashbin_t *iriap = NULL;
00059 static __u32 service_handle;
00060
00061 extern char *lmp_reasons[];
00062
00063 static void __iriap_close(struct iriap_cb *self);
00064 static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode);
00065 static void iriap_disconnect_indication(void *instance, void *sap,
00066 LM_REASON reason, struct sk_buff *skb);
00067 static void iriap_connect_indication(void *instance, void *sap,
00068 struct qos_info *qos, __u32 max_sdu_size,
00069 __u8 max_header_size,
00070 struct sk_buff *skb);
00071 static void iriap_connect_confirm(void *instance, void *sap,
00072 struct qos_info *qos,
00073 __u32 max_sdu_size, __u8 max_header_size,
00074 struct sk_buff *skb);
00075 static int iriap_data_indication(void *instance, void *sap,
00076 struct sk_buff *skb);
00077
00078
00079
00080
00081
00082
00083
00084 int __init iriap_init(void)
00085 {
00086 struct ias_object *obj;
00087 struct iriap_cb *server;
00088 __u8 oct_seq[6];
00089 __u16 hints;
00090
00091
00092 iriap = hashbin_new(HB_LOCAL);
00093 if (!iriap)
00094 return -ENOMEM;
00095
00096 objects = hashbin_new(HB_LOCAL);
00097 if (!objects) {
00098 WARNING(__FUNCTION__ "(), Can't allocate objects hashbin!\n");
00099 return -ENOMEM;
00100 }
00101
00102
00103
00104
00105 hints = irlmp_service_to_hint(S_COMPUTER);
00106 service_handle = irlmp_register_service(hints);
00107
00108
00109 obj = irias_new_object("Device", IAS_DEVICE_ID);
00110 irias_add_string_attrib(obj, "DeviceName", "Linux");
00111
00112 oct_seq[0] = 0x01;
00113 oct_seq[1] = 0x00;
00114 oct_seq[2] = 0x00;
00115 #ifdef CONFIG_IRDA_ULTRA
00116 oct_seq[2] |= 0x04;
00117 #endif
00118 irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3);
00119 irias_insert_object(obj);
00120
00121
00122
00123
00124
00125 server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
00126 if (!server) {
00127 IRDA_DEBUG(0, __FUNCTION__ "(), unable to open server\n");
00128 return -1;
00129 }
00130 iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
00131
00132 return 0;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141 void iriap_cleanup(void)
00142 {
00143 irlmp_unregister_service(service_handle);
00144
00145 hashbin_delete(iriap, (FREE_FUNC) __iriap_close);
00146 hashbin_delete(objects, (FREE_FUNC) __irias_delete_object);
00147 }
00148
00149
00150
00151
00152
00153
00154 struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
00155 CONFIRM_CALLBACK callback)
00156 {
00157 struct iriap_cb *self;
00158
00159 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00160
00161 self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
00162 if (!self) {
00163 WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
00164 return NULL;
00165 }
00166
00167
00168
00169
00170 memset(self, 0, sizeof(struct iriap_cb));
00171
00172 self->magic = IAS_MAGIC;
00173 self->mode = mode;
00174 if (mode == IAS_CLIENT)
00175 iriap_register_lsap(self, slsap_sel, mode);
00176
00177 self->confirm = callback;
00178 self->priv = priv;
00179
00180 init_timer(&self->watchdog_timer);
00181
00182 hashbin_insert(iriap, (queue_t *) self, (int) self, NULL);
00183
00184
00185 iriap_next_client_state(self, S_DISCONNECT);
00186 iriap_next_call_state(self, S_MAKE_CALL);
00187 iriap_next_server_state(self, R_DISCONNECT);
00188 iriap_next_r_connect_state(self, R_WAITING);
00189
00190 return self;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 static void __iriap_close(struct iriap_cb *self)
00200 {
00201 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00202
00203 ASSERT(self != NULL, return;);
00204 ASSERT(self->magic == IAS_MAGIC, return;);
00205
00206 del_timer(&self->watchdog_timer);
00207
00208 if (self->skb)
00209 dev_kfree_skb(self->skb);
00210
00211 self->magic = 0;
00212
00213 kfree(self);
00214 }
00215
00216
00217
00218
00219
00220
00221 void iriap_close(struct iriap_cb *self)
00222 {
00223 struct iriap_cb *entry;
00224
00225 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00226
00227 ASSERT(self != NULL, return;);
00228 ASSERT(self->magic == IAS_MAGIC, return;);
00229
00230 if (self->lsap) {
00231 irlmp_close_lsap(self->lsap);
00232 self->lsap = NULL;
00233 }
00234
00235 entry = (struct iriap_cb *) hashbin_remove(iriap, (int) self, NULL);
00236 ASSERT(entry == self, return;);
00237
00238 __iriap_close(self);
00239 }
00240
00241 static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
00242 {
00243 notify_t notify;
00244
00245 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00246
00247 irda_notify_init(¬ify);
00248 notify.connect_confirm = iriap_connect_confirm;
00249 notify.connect_indication = iriap_connect_indication;
00250 notify.disconnect_indication = iriap_disconnect_indication;
00251 notify.data_indication = iriap_data_indication;
00252 notify.instance = self;
00253 if (mode == IAS_CLIENT)
00254 strcpy(notify.name, "IrIAS cli");
00255 else
00256 strcpy(notify.name, "IrIAS srv");
00257
00258 self->lsap = irlmp_open_lsap(slsap_sel, ¬ify, 0);
00259 if (self->lsap == NULL) {
00260 ERROR(__FUNCTION__ "(), Unable to allocated LSAP!\n");
00261 return -1;
00262 }
00263 self->slsap_sel = self->lsap->slsap_sel;
00264
00265 return 0;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274 static void iriap_disconnect_indication(void *instance, void *sap,
00275 LM_REASON reason,
00276 struct sk_buff *userdata)
00277 {
00278 struct iriap_cb *self;
00279
00280 IRDA_DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
00281
00282 self = (struct iriap_cb *) instance;
00283
00284 ASSERT(self != NULL, return;);
00285 ASSERT(self->magic == IAS_MAGIC, return;);
00286
00287 ASSERT(iriap != NULL, return;);
00288
00289 del_timer(&self->watchdog_timer);
00290
00291 if (self->mode == IAS_CLIENT) {
00292 IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as client\n");
00293
00294
00295 iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION,
00296 NULL);
00297
00298
00299
00300
00301
00302 if (self->confirm)
00303 self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
00304 } else {
00305 IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as server\n");
00306 iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION,
00307 NULL);
00308 iriap_close(self);
00309 }
00310
00311 if (userdata)
00312 dev_kfree_skb(userdata);
00313 }
00314
00315
00316
00317
00318
00319
00320
00321 void iriap_disconnect_request(struct iriap_cb *self)
00322 {
00323 struct sk_buff *skb;
00324
00325 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00326
00327 ASSERT(self != NULL, return;);
00328 ASSERT(self->magic == IAS_MAGIC, return;);
00329
00330 skb = dev_alloc_skb(64);
00331 if (skb == NULL) {
00332 IRDA_DEBUG(0, __FUNCTION__
00333 "(), Could not allocate an sk_buff of length %d\n", 64);
00334 return;
00335 }
00336
00337
00338
00339
00340 skb_reserve(skb, LMP_MAX_HEADER);
00341
00342 irlmp_disconnect_request(self->lsap, skb);
00343 }
00344
00345 void iriap_getinfobasedetails_request(void)
00346 {
00347 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
00348 }
00349
00350 void iriap_getinfobasedetails_confirm(void)
00351 {
00352 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
00353 }
00354
00355 void iriap_getobjects_request(void)
00356 {
00357 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
00358 }
00359
00360 void iriap_getobjects_confirm(void)
00361 {
00362 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
00363 }
00364
00365 void iriap_getvalue(void)
00366 {
00367 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
00368 }
00369
00370
00371
00372
00373
00374
00375
00376 int iriap_getvaluebyclass_request(struct iriap_cb *self,
00377 __u32 saddr, __u32 daddr,
00378 char *name, char *attr)
00379 {
00380 struct sk_buff *skb;
00381 int name_len, attr_len;
00382 __u8 *frame;
00383
00384 ASSERT(self != NULL, return -1;);
00385 ASSERT(self->magic == IAS_MAGIC, return -1;);
00386
00387
00388 if (!daddr)
00389 return -1;
00390
00391 self->daddr = daddr;
00392 self->saddr = saddr;
00393
00394
00395
00396
00397 self->operation = GET_VALUE_BY_CLASS;
00398
00399
00400 iriap_start_watchdog_timer(self, 10*HZ);
00401
00402 skb = dev_alloc_skb(64);
00403 if (!skb)
00404 return -ENOMEM;
00405
00406 name_len = strlen(name);
00407 attr_len = strlen(attr);
00408
00409
00410 skb_reserve(skb, self->max_header_size);
00411 skb_put(skb, 3+name_len+attr_len);
00412 frame = skb->data;
00413
00414
00415 frame[0] = IAP_LST | GET_VALUE_BY_CLASS;
00416 frame[1] = name_len;
00417 memcpy(frame+2, name, name_len);
00418 frame[2+name_len] = attr_len;
00419 memcpy(frame+3+name_len, attr, attr_len);
00420
00421 iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, skb);
00422
00423 return 0;
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb)
00434 {
00435 struct ias_value *value;
00436 int charset;
00437 __u32 value_len;
00438 __u32 tmp_cpu32;
00439 __u16 obj_id;
00440 __u16 len;
00441 __u8 type;
00442 __u8 *fp;
00443 int n;
00444
00445 ASSERT(self != NULL, return;);
00446 ASSERT(self->magic == IAS_MAGIC, return;);
00447 ASSERT(skb != NULL, return;);
00448
00449
00450 fp = skb->data;
00451 n = 2;
00452
00453
00454 len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
00455
00456 IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
00457
00458
00459 obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
00460
00461 type = fp[n++];
00462 IRDA_DEBUG(4, __FUNCTION__ "(), Value type = %d\n", type);
00463
00464 switch (type) {
00465 case IAS_INTEGER:
00466 memcpy(&tmp_cpu32, fp+n, 4); n += 4;
00467 be32_to_cpus(&tmp_cpu32);
00468 value = irias_new_integer_value(tmp_cpu32);
00469
00470
00471 IRDA_DEBUG(4, __FUNCTION__ "(), lsap=%d\n", value->t.integer);
00472 break;
00473 case IAS_STRING:
00474 charset = fp[n++];
00475
00476 switch (charset) {
00477 case CS_ASCII:
00478 break;
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 default:
00490 IRDA_DEBUG(0, __FUNCTION__
00491 "(), charset %s, not supported\n",
00492 ias_charset_types[charset]);
00493
00494
00495 iriap_disconnect_request(self);
00496 dev_kfree_skb(skb);
00497 return;
00498
00499 }
00500 value_len = fp[n++];
00501 IRDA_DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
00502 ASSERT(value_len < 64, return;);
00503
00504
00505 fp[n+value_len] = 0x00;
00506
00507 IRDA_DEBUG(4, "Got string %s\n", fp+n);
00508 value = irias_new_string_value(fp+n);
00509 break;
00510 case IAS_OCT_SEQ:
00511 value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
00512 n += 2;
00513
00514 ASSERT(value_len <= 55, return;);
00515
00516 value = irias_new_octseq_value(fp+n, value_len);
00517 break;
00518 default:
00519 value = irias_new_missing_value();
00520 break;
00521 }
00522
00523
00524 iriap_disconnect_request(self);
00525
00526
00527
00528
00529 if (self->confirm)
00530 self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
00531 else {
00532 IRDA_DEBUG(0, __FUNCTION__ "(), missing handler!\n");
00533 irias_delete_value(value);
00534 }
00535 dev_kfree_skb(skb);
00536 }
00537
00538
00539
00540
00541
00542
00543
00544 void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id,
00545 __u8 ret_code, struct ias_value *value)
00546 {
00547 struct sk_buff *skb;
00548 int n;
00549 __u32 tmp_be32, tmp_be16;
00550 __u8 *fp;
00551
00552 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00553
00554 ASSERT(self != NULL, return;);
00555 ASSERT(self->magic == IAS_MAGIC, return;);
00556 ASSERT(value != NULL, return;);
00557 ASSERT(value->len <= 1024, return;);
00558
00559
00560 n = 0;
00561
00562
00563
00564
00565
00566
00567 skb = dev_alloc_skb(value->len + self->max_header_size + 32);
00568 if (!skb)
00569 return;
00570
00571
00572 skb_reserve(skb, self->max_header_size);
00573 skb_put(skb, 6);
00574
00575 fp = skb->data;
00576
00577
00578 fp[n++] = GET_VALUE_BY_CLASS | IAP_LST;
00579 fp[n++] = ret_code;
00580
00581
00582 tmp_be16 = __constant_htons(0x0001);
00583 memcpy(fp+n, &tmp_be16, 2); n += 2;
00584
00585
00586 tmp_be16 = cpu_to_be16(obj_id);
00587 memcpy(fp+n, &tmp_be16, 2); n += 2;
00588
00589 switch (value->type) {
00590 case IAS_STRING:
00591 skb_put(skb, 3 + value->len);
00592 fp[n++] = value->type;
00593 fp[n++] = 0;
00594 fp[n++] = (__u8) value->len;
00595 memcpy(fp+n, value->t.string, value->len); n+=value->len;
00596 break;
00597 case IAS_INTEGER:
00598 skb_put(skb, 5);
00599 fp[n++] = value->type;
00600
00601 tmp_be32 = cpu_to_be32(value->t.integer);
00602 memcpy(fp+n, &tmp_be32, 4); n += 4;
00603 break;
00604 case IAS_OCT_SEQ:
00605 skb_put(skb, 3 + value->len);
00606 fp[n++] = value->type;
00607
00608 tmp_be16 = cpu_to_be16(value->len);
00609 memcpy(fp+n, &tmp_be16, 2); n += 2;
00610 memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
00611 break;
00612 case IAS_MISSING:
00613 IRDA_DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
00614 skb_put(skb, 1);
00615 fp[n++] = value->type;
00616 break;
00617 default:
00618 IRDA_DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
00619 break;
00620 }
00621 iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
00622 }
00623
00624
00625
00626
00627
00628
00629
00630 void iriap_getvaluebyclass_indication(struct iriap_cb *self,
00631 struct sk_buff *skb)
00632 {
00633 struct ias_object *obj;
00634 struct ias_attrib *attrib;
00635 int name_len;
00636 int attr_len;
00637 char name[64];
00638 char attr[64];
00639 __u8 *fp;
00640 int n;
00641
00642 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00643
00644 ASSERT(self != NULL, return;);
00645 ASSERT(self->magic == IAS_MAGIC, return;);
00646 ASSERT(skb != NULL, return;);
00647
00648 fp = skb->data;
00649 n = 1;
00650
00651 name_len = fp[n++];
00652 memcpy(name, fp+n, name_len); n+=name_len;
00653 name[name_len] = '\0';
00654
00655 attr_len = fp[n++];
00656 memcpy(attr, fp+n, attr_len); n+=attr_len;
00657 attr[attr_len] = '\0';
00658
00659
00660 dev_kfree_skb(skb);
00661
00662 IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
00663 obj = irias_find_object(name);
00664
00665 if (obj == NULL) {
00666 IRDA_DEBUG(2, "LM-IAS: Object %s not found\n", name);
00667 iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
00668 &missing);
00669 return;
00670 }
00671 IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
00672
00673 attrib = irias_find_attrib(obj, attr);
00674 if (attrib == NULL) {
00675 IRDA_DEBUG(2, "LM-IAS: Attribute %s not found\n", attr);
00676 iriap_getvaluebyclass_response(self, obj->id,
00677 IAS_ATTRIB_UNKNOWN, &missing);
00678 return;
00679 }
00680
00681
00682 iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS,
00683 attrib->value);
00684
00685 return;
00686 }
00687
00688
00689
00690
00691
00692
00693
00694 void iriap_send_ack(struct iriap_cb *self)
00695 {
00696 struct sk_buff *skb;
00697 __u8 *frame;
00698
00699 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00700
00701 ASSERT(self != NULL, return;);
00702 ASSERT(self->magic == IAS_MAGIC, return;);
00703
00704 skb = dev_alloc_skb(64);
00705 if (!skb)
00706 return;
00707
00708
00709 skb_reserve(skb, self->max_header_size);
00710 skb_put(skb, 1);
00711 frame = skb->data;
00712
00713
00714 frame[0] = IAP_LST | IAP_ACK | self->operation;
00715
00716 irlmp_data_request(self->lsap, skb);
00717 }
00718
00719 void iriap_connect_request(struct iriap_cb *self)
00720 {
00721 int ret;
00722
00723 ASSERT(self != NULL, return;);
00724 ASSERT(self->magic == IAS_MAGIC, return;);
00725
00726 ret = irlmp_connect_request(self->lsap, LSAP_IAS,
00727 self->saddr, self->daddr,
00728 NULL, NULL);
00729 if (ret < 0) {
00730 IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
00731 self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
00732 }
00733 }
00734
00735
00736
00737
00738
00739
00740
00741 static void iriap_connect_confirm(void *instance, void *sap,
00742 struct qos_info *qos, __u32 max_seg_size,
00743 __u8 max_header_size,
00744 struct sk_buff *userdata)
00745 {
00746 struct iriap_cb *self;
00747
00748 self = (struct iriap_cb *) instance;
00749
00750 ASSERT(self != NULL, return;);
00751 ASSERT(self->magic == IAS_MAGIC, return;);
00752 ASSERT(userdata != NULL, return;);
00753
00754 self->max_data_size = max_seg_size;
00755 self->max_header_size = max_header_size;
00756
00757 del_timer(&self->watchdog_timer);
00758
00759 iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
00760 }
00761
00762
00763
00764
00765
00766
00767
00768 static void iriap_connect_indication(void *instance, void *sap,
00769 struct qos_info *qos, __u32 max_seg_size,
00770 __u8 max_header_size,
00771 struct sk_buff *userdata)
00772 {
00773 struct iriap_cb *self, *new;
00774
00775 IRDA_DEBUG(0, __FUNCTION__ "()\n");
00776
00777 self = (struct iriap_cb *) instance;
00778
00779 ASSERT(self != NULL, return;);
00780 ASSERT(self->magic == IAS_MAGIC, return;);
00781
00782
00783 new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
00784 if (!new) {
00785 IRDA_DEBUG(0, __FUNCTION__ "(), open failed\n");
00786 dev_kfree_skb(userdata);
00787 return;
00788 }
00789
00790
00791 new->lsap = irlmp_dup(self->lsap, new);
00792 if (!new->lsap) {
00793 IRDA_DEBUG(0, __FUNCTION__ "(), dup failed!\n");
00794 return;
00795 }
00796
00797 new->max_data_size = max_seg_size;
00798 new->max_header_size = max_header_size;
00799
00800
00801 self->lsap->dlsap_sel = LSAP_ANY;
00802 self->lsap->lsap_state = LSAP_DISCONNECTED;
00803
00804
00805 iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
00806 }
00807
00808
00809
00810
00811
00812
00813
00814 static int iriap_data_indication(void *instance, void *sap,
00815 struct sk_buff *skb)
00816 {
00817 struct iriap_cb *self;
00818 __u8 *frame;
00819 __u8 opcode;
00820
00821 IRDA_DEBUG(3, __FUNCTION__ "()\n");
00822
00823 self = (struct iriap_cb *) instance;
00824
00825 ASSERT(self != NULL, return 0;);
00826 ASSERT(self->magic == IAS_MAGIC, return 0;);
00827
00828 ASSERT(skb != NULL, return 0;);
00829
00830 frame = skb->data;
00831
00832 if (self->mode == IAS_SERVER) {
00833
00834 IRDA_DEBUG(4, __FUNCTION__ "(), Calling server!\n");
00835 iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
00836
00837 return 0;
00838 }
00839 opcode = frame[0];
00840 if (~opcode & IAP_LST) {
00841 WARNING(__FUNCTION__ "(), IrIAS multiframe commands or "
00842 "results is not implemented yet!\n");
00843 dev_kfree_skb(skb);
00844 return 0;
00845 }
00846
00847
00848 if (opcode & IAP_ACK) {
00849 IRDA_DEBUG(0, __FUNCTION__ "() Got ack frame!\n");
00850 dev_kfree_skb(skb);
00851 return 0;
00852 }
00853
00854 opcode &= ~IAP_LST;
00855
00856 switch (opcode) {
00857 case GET_INFO_BASE:
00858 IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
00859 dev_kfree_skb(skb);
00860 break;
00861 case GET_VALUE_BY_CLASS:
00862 iriap_do_call_event(self, IAP_RECV_F_LST, NULL);
00863
00864 switch (frame[1]) {
00865 case IAS_SUCCESS:
00866 iriap_getvaluebyclass_confirm(self, skb);
00867 break;
00868 case IAS_CLASS_UNKNOWN:
00869 WARNING(__FUNCTION__ "(), No such class!\n");
00870
00871 iriap_disconnect_request(self);
00872
00873
00874
00875
00876
00877 if (self->confirm)
00878 self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
00879 self->priv);
00880 dev_kfree_skb(skb);
00881 break;
00882 case IAS_ATTRIB_UNKNOWN:
00883 WARNING(__FUNCTION__ "(), No such attribute!\n");
00884
00885 iriap_disconnect_request(self);
00886
00887
00888
00889
00890
00891 if (self->confirm)
00892 self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
00893 self->priv);
00894 dev_kfree_skb(skb);
00895 break;
00896 }
00897 break;
00898 default:
00899 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n",
00900 opcode);
00901 dev_kfree_skb(skb);
00902 break;
00903 }
00904 return 0;
00905 }
00906
00907
00908
00909
00910
00911
00912
00913 void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
00914 {
00915 __u8 *fp;
00916 __u8 opcode;
00917
00918 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00919
00920 ASSERT(self != NULL, return;);
00921 ASSERT(self->magic == IAS_MAGIC, return;);
00922 ASSERT(skb != NULL, return;);
00923
00924 fp = skb->data;
00925
00926 opcode = fp[0];
00927 if (~opcode & 0x80) {
00928 WARNING(__FUNCTION__ "(), IrIAS multiframe commands or results"
00929 "is not implemented yet!\n");
00930 return;
00931 }
00932 opcode &= 0x7f;
00933
00934 switch (opcode) {
00935 case GET_INFO_BASE:
00936 WARNING(__FUNCTION__
00937 "(), GetInfoBaseDetails not implemented yet!\n");
00938 break;
00939 case GET_VALUE_BY_CLASS:
00940 iriap_getvaluebyclass_indication(self, skb);
00941 break;
00942 }
00943 }
00944
00945
00946
00947
00948
00949
00950
00951 void iriap_watchdog_timer_expired(void *data)
00952 {
00953 struct iriap_cb *self = (struct iriap_cb *) data;
00954
00955 ASSERT(self != NULL, return;);
00956 ASSERT(self->magic == IAS_MAGIC, return;);
00957
00958
00959 }
00960
00961 #ifdef CONFIG_PROC_FS
00962
00963 static char *ias_value_types[] = {
00964 "IAS_MISSING",
00965 "IAS_INTEGER",
00966 "IAS_OCT_SEQ",
00967 "IAS_STRING"
00968 };
00969
00970 int irias_proc_read(char *buf, char **start, off_t offset, int len, int unused)
00971 {
00972 struct ias_object *obj;
00973 struct ias_attrib *attrib;
00974 unsigned long flags;
00975
00976 ASSERT( objects != NULL, return 0;);
00977
00978 save_flags( flags);
00979 cli();
00980
00981 len = 0;
00982
00983 len += sprintf(buf+len, "LM-IAS Objects:\n");
00984
00985
00986 obj = (struct ias_object *) hashbin_get_first(objects);
00987 while ( obj != NULL) {
00988 ASSERT(obj->magic == IAS_OBJECT_MAGIC, return 0;);
00989
00990 len += sprintf(buf+len, "name: %s, ", obj->name);
00991 len += sprintf(buf+len, "id=%d", obj->id);
00992 len += sprintf(buf+len, "\n");
00993
00994
00995 attrib = (struct ias_attrib *)
00996 hashbin_get_first(obj->attribs);
00997 while (attrib != NULL) {
00998 ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
00999
01000 len += sprintf(buf+len, " - Attribute name: \"%s\", ",
01001 attrib->name);
01002 len += sprintf(buf+len, "value[%s]: ",
01003 ias_value_types[attrib->value->type]);
01004
01005 switch (attrib->value->type) {
01006 case IAS_INTEGER:
01007 len += sprintf(buf+len, "%d\n",
01008 attrib->value->t.integer);
01009 break;
01010 case IAS_STRING:
01011 len += sprintf(buf+len, "\"%s\"\n",
01012 attrib->value->t.string);
01013 break;
01014 case IAS_OCT_SEQ:
01015 len += sprintf(buf+len, "octet sequence\n");
01016 break;
01017 case IAS_MISSING:
01018 len += sprintf(buf+len, "missing\n");
01019 break;
01020 default:
01021 IRDA_DEBUG(0, __FUNCTION__
01022 "(), Unknown value type!\n");
01023 return -1;
01024 }
01025 len += sprintf(buf+len, "\n");
01026
01027 attrib = (struct ias_attrib *)
01028 hashbin_get_next(obj->attribs);
01029 }
01030 obj = (struct ias_object *) hashbin_get_next(objects);
01031 }
01032 restore_flags(flags);
01033
01034 return len;
01035 }
01036
01037 #endif