1/********************************************************************* 2 * 3 * Filename: iriap.c 4 * Version: 0.8 5 * Description: Information Access Protocol (IAP) 6 * Status: Experimental. 7 * Author: Dag Brattli <dagb@cs.uit.no> 8 * Created at: Thu Aug 21 00:02:07 1997 9 * Modified at: Sat Dec 25 16:42:42 1999 10 * Modified by: Dag Brattli <dagb@cs.uit.no> 11 * 12 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 13 * All Rights Reserved. 14 * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com> 15 * 16 * This program is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU General Public License as 18 * published by the Free Software Foundation; either version 2 of 19 * the License, or (at your option) any later version. 20 * 21 * Neither Dag Brattli nor University of Tromsø admit liability nor 22 * provide warranty for any of this software. This material is 23 * provided "AS-IS" and at no charge. 24 * 25 ********************************************************************/ 26 27#include <linux/module.h> 28#include <linux/types.h> 29#include <linux/skbuff.h> 30#include <linux/fs.h> 31#include <linux/string.h> 32#include <linux/init.h> 33#include <linux/seq_file.h> 34#include <linux/slab.h> 35 36#include <asm/byteorder.h> 37#include <asm/unaligned.h> 38 39#include <net/irda/irda.h> 40#include <net/irda/irttp.h> 41#include <net/irda/irlmp.h> 42#include <net/irda/irias_object.h> 43#include <net/irda/iriap_event.h> 44#include <net/irda/iriap.h> 45 46/* FIXME: This one should go in irlmp.c */ 47static const char *const ias_charset_types[] __maybe_unused = { 48 "CS_ASCII", 49 "CS_ISO_8859_1", 50 "CS_ISO_8859_2", 51 "CS_ISO_8859_3", 52 "CS_ISO_8859_4", 53 "CS_ISO_8859_5", 54 "CS_ISO_8859_6", 55 "CS_ISO_8859_7", 56 "CS_ISO_8859_8", 57 "CS_ISO_8859_9", 58 "CS_UNICODE" 59}; 60 61static hashbin_t *iriap = NULL; 62static void *service_handle; 63 64static void __iriap_close(struct iriap_cb *self); 65static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode); 66static void iriap_disconnect_indication(void *instance, void *sap, 67 LM_REASON reason, struct sk_buff *skb); 68static void iriap_connect_indication(void *instance, void *sap, 69 struct qos_info *qos, __u32 max_sdu_size, 70 __u8 max_header_size, 71 struct sk_buff *skb); 72static void iriap_connect_confirm(void *instance, void *sap, 73 struct qos_info *qos, 74 __u32 max_sdu_size, __u8 max_header_size, 75 struct sk_buff *skb); 76static int iriap_data_indication(void *instance, void *sap, 77 struct sk_buff *skb); 78 79static void iriap_watchdog_timer_expired(void *data); 80 81static inline void iriap_start_watchdog_timer(struct iriap_cb *self, 82 int timeout) 83{ 84 irda_start_timer(&self->watchdog_timer, timeout, self, 85 iriap_watchdog_timer_expired); 86} 87 88static struct lock_class_key irias_objects_key; 89 90/* 91 * Function iriap_init (void) 92 * 93 * Initializes the IrIAP layer, called by the module initialization code 94 * in irmod.c 95 */ 96int __init iriap_init(void) 97{ 98 struct ias_object *obj; 99 struct iriap_cb *server; 100 __u8 oct_seq[6]; 101 __u16 hints; 102 103 /* Allocate master array */ 104 iriap = hashbin_new(HB_LOCK); 105 if (!iriap) 106 return -ENOMEM; 107 108 /* Object repository - defined in irias_object.c */ 109 irias_objects = hashbin_new(HB_LOCK); 110 if (!irias_objects) { 111 net_warn_ratelimited("%s: Can't allocate irias_objects hashbin!\n", 112 __func__); 113 hashbin_delete(iriap, NULL); 114 return -ENOMEM; 115 } 116 117 lockdep_set_class_and_name(&irias_objects->hb_spinlock, &irias_objects_key, 118 "irias_objects"); 119 120 /* 121 * Register some default services for IrLMP 122 */ 123 hints = irlmp_service_to_hint(S_COMPUTER); 124 service_handle = irlmp_register_service(hints); 125 126 /* Register the Device object with LM-IAS */ 127 obj = irias_new_object("Device", IAS_DEVICE_ID); 128 irias_add_string_attrib(obj, "DeviceName", "Linux", IAS_KERNEL_ATTR); 129 130 oct_seq[0] = 0x01; /* Version 1 */ 131 oct_seq[1] = 0x00; /* IAS support bits */ 132 oct_seq[2] = 0x00; /* LM-MUX support bits */ 133#ifdef CONFIG_IRDA_ULTRA 134 oct_seq[2] |= 0x04; /* Connectionless Data support */ 135#endif 136 irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3, 137 IAS_KERNEL_ATTR); 138 irias_insert_object(obj); 139 140 /* 141 * Register server support with IrLMP so we can accept incoming 142 * connections 143 */ 144 server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL); 145 if (!server) { 146 pr_debug("%s(), unable to open server\n", __func__); 147 return -1; 148 } 149 iriap_register_lsap(server, LSAP_IAS, IAS_SERVER); 150 151 return 0; 152} 153 154/* 155 * Function iriap_cleanup (void) 156 * 157 * Initializes the IrIAP layer, called by the module cleanup code in 158 * irmod.c 159 */ 160void iriap_cleanup(void) 161{ 162 irlmp_unregister_service(service_handle); 163 164 hashbin_delete(iriap, (FREE_FUNC) __iriap_close); 165 hashbin_delete(irias_objects, (FREE_FUNC) __irias_delete_object); 166} 167 168/* 169 * Function iriap_open (void) 170 * 171 * Opens an instance of the IrIAP layer, and registers with IrLMP 172 */ 173struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, 174 CONFIRM_CALLBACK callback) 175{ 176 struct iriap_cb *self; 177 178 self = kzalloc(sizeof(*self), GFP_ATOMIC); 179 if (!self) 180 return NULL; 181 182 /* 183 * Initialize instance 184 */ 185 186 self->magic = IAS_MAGIC; 187 self->mode = mode; 188 if (mode == IAS_CLIENT) 189 iriap_register_lsap(self, slsap_sel, mode); 190 191 self->confirm = callback; 192 self->priv = priv; 193 194 /* iriap_getvaluebyclass_request() will construct packets before 195 * we connect, so this must have a sane value... Jean II */ 196 self->max_header_size = LMP_MAX_HEADER; 197 198 init_timer(&self->watchdog_timer); 199 200 hashbin_insert(iriap, (irda_queue_t *) self, (long) self, NULL); 201 202 /* Initialize state machines */ 203 iriap_next_client_state(self, S_DISCONNECT); 204 iriap_next_call_state(self, S_MAKE_CALL); 205 iriap_next_server_state(self, R_DISCONNECT); 206 iriap_next_r_connect_state(self, R_WAITING); 207 208 return self; 209} 210EXPORT_SYMBOL(iriap_open); 211 212/* 213 * Function __iriap_close (self) 214 * 215 * Removes (deallocates) the IrIAP instance 216 * 217 */ 218static void __iriap_close(struct iriap_cb *self) 219{ 220 IRDA_ASSERT(self != NULL, return;); 221 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 222 223 del_timer(&self->watchdog_timer); 224 225 if (self->request_skb) 226 dev_kfree_skb(self->request_skb); 227 228 self->magic = 0; 229 230 kfree(self); 231} 232 233/* 234 * Function iriap_close (void) 235 * 236 * Closes IrIAP and deregisters with IrLMP 237 */ 238void iriap_close(struct iriap_cb *self) 239{ 240 struct iriap_cb *entry; 241 242 IRDA_ASSERT(self != NULL, return;); 243 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 244 245 if (self->lsap) { 246 irlmp_close_lsap(self->lsap); 247 self->lsap = NULL; 248 } 249 250 entry = (struct iriap_cb *) hashbin_remove(iriap, (long) self, NULL); 251 IRDA_ASSERT(entry == self, return;); 252 253 __iriap_close(self); 254} 255EXPORT_SYMBOL(iriap_close); 256 257static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode) 258{ 259 notify_t notify; 260 261 irda_notify_init(¬ify); 262 notify.connect_confirm = iriap_connect_confirm; 263 notify.connect_indication = iriap_connect_indication; 264 notify.disconnect_indication = iriap_disconnect_indication; 265 notify.data_indication = iriap_data_indication; 266 notify.instance = self; 267 if (mode == IAS_CLIENT) 268 strcpy(notify.name, "IrIAS cli"); 269 else 270 strcpy(notify.name, "IrIAS srv"); 271 272 self->lsap = irlmp_open_lsap(slsap_sel, ¬ify, 0); 273 if (self->lsap == NULL) { 274 net_err_ratelimited("%s: Unable to allocated LSAP!\n", 275 __func__); 276 return -1; 277 } 278 self->slsap_sel = self->lsap->slsap_sel; 279 280 return 0; 281} 282 283/* 284 * Function iriap_disconnect_indication (handle, reason) 285 * 286 * Got disconnect, so clean up everything associated with this connection 287 * 288 */ 289static void iriap_disconnect_indication(void *instance, void *sap, 290 LM_REASON reason, 291 struct sk_buff *skb) 292{ 293 struct iriap_cb *self; 294 295 pr_debug("%s(), reason=%s [%d]\n", __func__, 296 irlmp_reason_str(reason), reason); 297 298 self = instance; 299 300 IRDA_ASSERT(self != NULL, return;); 301 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 302 303 IRDA_ASSERT(iriap != NULL, return;); 304 305 del_timer(&self->watchdog_timer); 306 307 /* Not needed */ 308 if (skb) 309 dev_kfree_skb(skb); 310 311 if (self->mode == IAS_CLIENT) { 312 pr_debug("%s(), disconnect as client\n", __func__); 313 314 315 iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION, 316 NULL); 317 /* 318 * Inform service user that the request failed by sending 319 * it a NULL value. Warning, the client might close us, so 320 * remember no to use self anymore after calling confirm 321 */ 322 if (self->confirm) 323 self->confirm(IAS_DISCONNECT, 0, NULL, self->priv); 324 } else { 325 pr_debug("%s(), disconnect as server\n", __func__); 326 iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION, 327 NULL); 328 iriap_close(self); 329 } 330} 331 332/* 333 * Function iriap_disconnect_request (handle) 334 */ 335static void iriap_disconnect_request(struct iriap_cb *self) 336{ 337 struct sk_buff *tx_skb; 338 339 IRDA_ASSERT(self != NULL, return;); 340 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 341 342 tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC); 343 if (tx_skb == NULL) { 344 pr_debug("%s(), Could not allocate an sk_buff of length %d\n", 345 __func__, LMP_MAX_HEADER); 346 return; 347 } 348 349 /* 350 * Reserve space for MUX control and LAP header 351 */ 352 skb_reserve(tx_skb, LMP_MAX_HEADER); 353 354 irlmp_disconnect_request(self->lsap, tx_skb); 355} 356 357/* 358 * Function iriap_getvaluebyclass (addr, name, attr) 359 * 360 * Retrieve all values from attribute in all objects with given class 361 * name 362 */ 363int iriap_getvaluebyclass_request(struct iriap_cb *self, 364 __u32 saddr, __u32 daddr, 365 char *name, char *attr) 366{ 367 struct sk_buff *tx_skb; 368 int name_len, attr_len, skb_len; 369 __u8 *frame; 370 371 IRDA_ASSERT(self != NULL, return -1;); 372 IRDA_ASSERT(self->magic == IAS_MAGIC, return -1;); 373 374 /* Client must supply the destination device address */ 375 if (!daddr) 376 return -1; 377 378 self->daddr = daddr; 379 self->saddr = saddr; 380 381 /* 382 * Save operation, so we know what the later indication is about 383 */ 384 self->operation = GET_VALUE_BY_CLASS; 385 386 /* Give ourselves 10 secs to finish this operation */ 387 iriap_start_watchdog_timer(self, 10*HZ); 388 389 name_len = strlen(name); /* Up to IAS_MAX_CLASSNAME = 60 */ 390 attr_len = strlen(attr); /* Up to IAS_MAX_ATTRIBNAME = 60 */ 391 392 skb_len = self->max_header_size+2+name_len+1+attr_len+4; 393 tx_skb = alloc_skb(skb_len, GFP_ATOMIC); 394 if (!tx_skb) 395 return -ENOMEM; 396 397 /* Reserve space for MUX and LAP header */ 398 skb_reserve(tx_skb, self->max_header_size); 399 skb_put(tx_skb, 3+name_len+attr_len); 400 frame = tx_skb->data; 401 402 /* Build frame */ 403 frame[0] = IAP_LST | GET_VALUE_BY_CLASS; 404 frame[1] = name_len; /* Insert length of name */ 405 memcpy(frame+2, name, name_len); /* Insert name */ 406 frame[2+name_len] = attr_len; /* Insert length of attr */ 407 memcpy(frame+3+name_len, attr, attr_len); /* Insert attr */ 408 409 iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, tx_skb); 410 411 /* Drop reference count - see state_s_disconnect(). */ 412 dev_kfree_skb(tx_skb); 413 414 return 0; 415} 416EXPORT_SYMBOL(iriap_getvaluebyclass_request); 417 418/* 419 * Function iriap_getvaluebyclass_confirm (self, skb) 420 * 421 * Got result from GetValueByClass command. Parse it and return result 422 * to service user. 423 * 424 */ 425static void iriap_getvaluebyclass_confirm(struct iriap_cb *self, 426 struct sk_buff *skb) 427{ 428 struct ias_value *value; 429 int charset; 430 __u32 value_len; 431 __u32 tmp_cpu32; 432 __u16 obj_id; 433 __u16 len; 434 __u8 type; 435 __u8 *fp; 436 int n; 437 438 IRDA_ASSERT(self != NULL, return;); 439 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 440 IRDA_ASSERT(skb != NULL, return;); 441 442 /* Initialize variables */ 443 fp = skb->data; 444 n = 2; 445 446 /* Get length, MSB first */ 447 len = get_unaligned_be16(fp + n); 448 n += 2; 449 450 pr_debug("%s(), len=%d\n", __func__, len); 451 452 /* Get object ID, MSB first */ 453 obj_id = get_unaligned_be16(fp + n); 454 n += 2; 455 456 type = fp[n++]; 457 pr_debug("%s(), Value type = %d\n", __func__, type); 458 459 switch (type) { 460 case IAS_INTEGER: 461 memcpy(&tmp_cpu32, fp+n, 4); n += 4; 462 be32_to_cpus(&tmp_cpu32); 463 value = irias_new_integer_value(tmp_cpu32); 464 465 /* Legal values restricted to 0x01-0x6f, page 15 irttp */ 466 pr_debug("%s(), lsap=%d\n", __func__, value->t.integer); 467 break; 468 case IAS_STRING: 469 charset = fp[n++]; 470 471 switch (charset) { 472 case CS_ASCII: 473 break; 474/* case CS_ISO_8859_1: */ 475/* case CS_ISO_8859_2: */ 476/* case CS_ISO_8859_3: */ 477/* case CS_ISO_8859_4: */ 478/* case CS_ISO_8859_5: */ 479/* case CS_ISO_8859_6: */ 480/* case CS_ISO_8859_7: */ 481/* case CS_ISO_8859_8: */ 482/* case CS_ISO_8859_9: */ 483/* case CS_UNICODE: */ 484 default: 485 pr_debug("%s(), charset [%d] %s, not supported\n", 486 __func__, charset, 487 charset < ARRAY_SIZE(ias_charset_types) ? 488 ias_charset_types[charset] : 489 "(unknown)"); 490 491 /* Aborting, close connection! */ 492 iriap_disconnect_request(self); 493 return; 494 /* break; */ 495 } 496 value_len = fp[n++]; 497 pr_debug("%s(), strlen=%d\n", __func__, value_len); 498 499 /* Make sure the string is null-terminated */ 500 if (n + value_len < skb->len) 501 fp[n + value_len] = 0x00; 502 pr_debug("Got string %s\n", fp+n); 503 504 /* Will truncate to IAS_MAX_STRING bytes */ 505 value = irias_new_string_value(fp+n); 506 break; 507 case IAS_OCT_SEQ: 508 value_len = get_unaligned_be16(fp + n); 509 n += 2; 510 511 /* Will truncate to IAS_MAX_OCTET_STRING bytes */ 512 value = irias_new_octseq_value(fp+n, value_len); 513 break; 514 default: 515 value = irias_new_missing_value(); 516 break; 517 } 518 519 /* Finished, close connection! */ 520 iriap_disconnect_request(self); 521 522 /* Warning, the client might close us, so remember no to use self 523 * anymore after calling confirm 524 */ 525 if (self->confirm) 526 self->confirm(IAS_SUCCESS, obj_id, value, self->priv); 527 else { 528 pr_debug("%s(), missing handler!\n", __func__); 529 irias_delete_value(value); 530 } 531} 532 533/* 534 * Function iriap_getvaluebyclass_response () 535 * 536 * Send answer back to remote LM-IAS 537 * 538 */ 539static void iriap_getvaluebyclass_response(struct iriap_cb *self, 540 __u16 obj_id, 541 __u8 ret_code, 542 struct ias_value *value) 543{ 544 struct sk_buff *tx_skb; 545 int n; 546 __be32 tmp_be32; 547 __be16 tmp_be16; 548 __u8 *fp; 549 550 IRDA_ASSERT(self != NULL, return;); 551 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 552 IRDA_ASSERT(value != NULL, return;); 553 IRDA_ASSERT(value->len <= 1024, return;); 554 555 /* Initialize variables */ 556 n = 0; 557 558 /* 559 * We must adjust the size of the response after the length of the 560 * value. We add 32 bytes because of the 6 bytes for the frame and 561 * max 5 bytes for the value coding. 562 */ 563 tx_skb = alloc_skb(value->len + self->max_header_size + 32, 564 GFP_ATOMIC); 565 if (!tx_skb) 566 return; 567 568 /* Reserve space for MUX and LAP header */ 569 skb_reserve(tx_skb, self->max_header_size); 570 skb_put(tx_skb, 6); 571 572 fp = tx_skb->data; 573 574 /* Build frame */ 575 fp[n++] = GET_VALUE_BY_CLASS | IAP_LST; 576 fp[n++] = ret_code; 577 578 /* Insert list length (MSB first) */ 579 tmp_be16 = htons(0x0001); 580 memcpy(fp+n, &tmp_be16, 2); n += 2; 581 582 /* Insert object identifier ( MSB first) */ 583 tmp_be16 = cpu_to_be16(obj_id); 584 memcpy(fp+n, &tmp_be16, 2); n += 2; 585 586 switch (value->type) { 587 case IAS_STRING: 588 skb_put(tx_skb, 3 + value->len); 589 fp[n++] = value->type; 590 fp[n++] = 0; /* ASCII */ 591 fp[n++] = (__u8) value->len; 592 memcpy(fp+n, value->t.string, value->len); n+=value->len; 593 break; 594 case IAS_INTEGER: 595 skb_put(tx_skb, 5); 596 fp[n++] = value->type; 597 598 tmp_be32 = cpu_to_be32(value->t.integer); 599 memcpy(fp+n, &tmp_be32, 4); n += 4; 600 break; 601 case IAS_OCT_SEQ: 602 skb_put(tx_skb, 3 + value->len); 603 fp[n++] = value->type; 604 605 tmp_be16 = cpu_to_be16(value->len); 606 memcpy(fp+n, &tmp_be16, 2); n += 2; 607 memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len; 608 break; 609 case IAS_MISSING: 610 pr_debug("%s: sending IAS_MISSING\n", __func__); 611 skb_put(tx_skb, 1); 612 fp[n++] = value->type; 613 break; 614 default: 615 pr_debug("%s(), type not implemented!\n", __func__); 616 break; 617 } 618 iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, tx_skb); 619 620 /* Drop reference count - see state_r_execute(). */ 621 dev_kfree_skb(tx_skb); 622} 623 624/* 625 * Function iriap_getvaluebyclass_indication (self, skb) 626 * 627 * getvaluebyclass is requested from peer LM-IAS 628 * 629 */ 630static void iriap_getvaluebyclass_indication(struct iriap_cb *self, 631 struct sk_buff *skb) 632{ 633 struct ias_object *obj; 634 struct ias_attrib *attrib; 635 int name_len; 636 int attr_len; 637 char name[IAS_MAX_CLASSNAME + 1]; /* 60 bytes */ 638 char attr[IAS_MAX_ATTRIBNAME + 1]; /* 60 bytes */ 639 __u8 *fp; 640 int n; 641 642 IRDA_ASSERT(self != NULL, return;); 643 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 644 IRDA_ASSERT(skb != NULL, return;); 645 646 fp = skb->data; 647 n = 1; 648 649 name_len = fp[n++]; 650 651 IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;); 652 653 memcpy(name, fp+n, name_len); n+=name_len; 654 name[name_len] = '\0'; 655 656 attr_len = fp[n++]; 657 658 IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;); 659 660 memcpy(attr, fp+n, attr_len); n+=attr_len; 661 attr[attr_len] = '\0'; 662 663 pr_debug("LM-IAS: Looking up %s: %s\n", name, attr); 664 obj = irias_find_object(name); 665 666 if (obj == NULL) { 667 pr_debug("LM-IAS: Object %s not found\n", name); 668 iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN, 669 &irias_missing); 670 return; 671 } 672 pr_debug("LM-IAS: found %s, id=%d\n", obj->name, obj->id); 673 674 attrib = irias_find_attrib(obj, attr); 675 if (attrib == NULL) { 676 pr_debug("LM-IAS: Attribute %s not found\n", attr); 677 iriap_getvaluebyclass_response(self, obj->id, 678 IAS_ATTRIB_UNKNOWN, 679 &irias_missing); 680 return; 681 } 682 683 /* We have a match; send the value. */ 684 iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS, 685 attrib->value); 686} 687 688/* 689 * Function iriap_send_ack (void) 690 * 691 * Currently not used 692 * 693 */ 694void iriap_send_ack(struct iriap_cb *self) 695{ 696 struct sk_buff *tx_skb; 697 __u8 *frame; 698 699 IRDA_ASSERT(self != NULL, return;); 700 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 701 702 tx_skb = alloc_skb(LMP_MAX_HEADER + 1, GFP_ATOMIC); 703 if (!tx_skb) 704 return; 705 706 /* Reserve space for MUX and LAP header */ 707 skb_reserve(tx_skb, self->max_header_size); 708 skb_put(tx_skb, 1); 709 frame = tx_skb->data; 710 711 /* Build frame */ 712 frame[0] = IAP_LST | IAP_ACK | self->operation; 713 714 irlmp_data_request(self->lsap, tx_skb); 715} 716 717void iriap_connect_request(struct iriap_cb *self) 718{ 719 int ret; 720 721 IRDA_ASSERT(self != NULL, return;); 722 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 723 724 ret = irlmp_connect_request(self->lsap, LSAP_IAS, 725 self->saddr, self->daddr, 726 NULL, NULL); 727 if (ret < 0) { 728 pr_debug("%s(), connect failed!\n", __func__); 729 self->confirm(IAS_DISCONNECT, 0, NULL, self->priv); 730 } 731} 732 733/* 734 * Function iriap_connect_confirm (handle, skb) 735 * 736 * LSAP connection confirmed! 737 * 738 */ 739static void iriap_connect_confirm(void *instance, void *sap, 740 struct qos_info *qos, __u32 max_seg_size, 741 __u8 max_header_size, 742 struct sk_buff *skb) 743{ 744 struct iriap_cb *self; 745 746 self = instance; 747 748 IRDA_ASSERT(self != NULL, return;); 749 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 750 IRDA_ASSERT(skb != NULL, return;); 751 752 self->max_data_size = max_seg_size; 753 self->max_header_size = max_header_size; 754 755 del_timer(&self->watchdog_timer); 756 757 iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, skb); 758 759 /* Drop reference count - see state_s_make_call(). */ 760 dev_kfree_skb(skb); 761} 762 763/* 764 * Function iriap_connect_indication ( handle, skb) 765 * 766 * Remote LM-IAS is requesting connection 767 * 768 */ 769static void iriap_connect_indication(void *instance, void *sap, 770 struct qos_info *qos, __u32 max_seg_size, 771 __u8 max_header_size, 772 struct sk_buff *skb) 773{ 774 struct iriap_cb *self, *new; 775 776 self = instance; 777 778 IRDA_ASSERT(skb != NULL, return;); 779 IRDA_ASSERT(self != NULL, goto out;); 780 IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;); 781 782 /* Start new server */ 783 new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL); 784 if (!new) { 785 pr_debug("%s(), open failed\n", __func__); 786 goto out; 787 } 788 789 /* Now attach up the new "socket" */ 790 new->lsap = irlmp_dup(self->lsap, new); 791 if (!new->lsap) { 792 pr_debug("%s(), dup failed!\n", __func__); 793 goto out; 794 } 795 796 new->max_data_size = max_seg_size; 797 new->max_header_size = max_header_size; 798 799 /* Clean up the original one to keep it in listen state */ 800 irlmp_listen(self->lsap); 801 802 iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, skb); 803 804out: 805 /* Drop reference count - see state_r_disconnect(). */ 806 dev_kfree_skb(skb); 807} 808 809/* 810 * Function iriap_data_indication (handle, skb) 811 * 812 * Receives data from connection identified by handle from IrLMP 813 * 814 */ 815static int iriap_data_indication(void *instance, void *sap, 816 struct sk_buff *skb) 817{ 818 struct iriap_cb *self; 819 __u8 *frame; 820 __u8 opcode; 821 822 self = instance; 823 824 IRDA_ASSERT(skb != NULL, return 0;); 825 IRDA_ASSERT(self != NULL, goto out;); 826 IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;); 827 828 frame = skb->data; 829 830 if (self->mode == IAS_SERVER) { 831 /* Call server */ 832 pr_debug("%s(), Calling server!\n", __func__); 833 iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb); 834 goto out; 835 } 836 opcode = frame[0]; 837 if (~opcode & IAP_LST) { 838 net_warn_ratelimited("%s:, IrIAS multiframe commands or results is not implemented yet!\n", 839 __func__); 840 goto out; 841 } 842 843 /* Check for ack frames since they don't contain any data */ 844 if (opcode & IAP_ACK) { 845 pr_debug("%s() Got ack frame!\n", __func__); 846 goto out; 847 } 848 849 opcode &= ~IAP_LST; /* Mask away LST bit */ 850 851 switch (opcode) { 852 case GET_INFO_BASE: 853 pr_debug("IrLMP GetInfoBaseDetails not implemented!\n"); 854 break; 855 case GET_VALUE_BY_CLASS: 856 iriap_do_call_event(self, IAP_RECV_F_LST, NULL); 857 858 switch (frame[1]) { 859 case IAS_SUCCESS: 860 iriap_getvaluebyclass_confirm(self, skb); 861 break; 862 case IAS_CLASS_UNKNOWN: 863 pr_debug("%s(), No such class!\n", __func__); 864 /* Finished, close connection! */ 865 iriap_disconnect_request(self); 866 867 /* 868 * Warning, the client might close us, so remember 869 * no to use self anymore after calling confirm 870 */ 871 if (self->confirm) 872 self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, 873 self->priv); 874 break; 875 case IAS_ATTRIB_UNKNOWN: 876 pr_debug("%s(), No such attribute!\n", __func__); 877 /* Finished, close connection! */ 878 iriap_disconnect_request(self); 879 880 /* 881 * Warning, the client might close us, so remember 882 * no to use self anymore after calling confirm 883 */ 884 if (self->confirm) 885 self->confirm(IAS_ATTRIB_UNKNOWN, 0, NULL, 886 self->priv); 887 break; 888 } 889 break; 890 default: 891 pr_debug("%s(), Unknown op-code: %02x\n", __func__, 892 opcode); 893 break; 894 } 895 896out: 897 /* Cleanup - sub-calls will have done skb_get() as needed. */ 898 dev_kfree_skb(skb); 899 return 0; 900} 901 902/* 903 * Function iriap_call_indication (self, skb) 904 * 905 * Received call to server from peer LM-IAS 906 * 907 */ 908void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb) 909{ 910 __u8 *fp; 911 __u8 opcode; 912 913 IRDA_ASSERT(self != NULL, return;); 914 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 915 IRDA_ASSERT(skb != NULL, return;); 916 917 fp = skb->data; 918 919 opcode = fp[0]; 920 if (~opcode & 0x80) { 921 net_warn_ratelimited("%s: IrIAS multiframe commands or results is not implemented yet!\n", 922 __func__); 923 return; 924 } 925 opcode &= 0x7f; /* Mask away LST bit */ 926 927 switch (opcode) { 928 case GET_INFO_BASE: 929 net_warn_ratelimited("%s: GetInfoBaseDetails not implemented yet!\n", 930 __func__); 931 break; 932 case GET_VALUE_BY_CLASS: 933 iriap_getvaluebyclass_indication(self, skb); 934 break; 935 } 936 /* skb will be cleaned up in iriap_data_indication */ 937} 938 939/* 940 * Function iriap_watchdog_timer_expired (data) 941 * 942 * Query has taken too long time, so abort 943 * 944 */ 945static void iriap_watchdog_timer_expired(void *data) 946{ 947 struct iriap_cb *self = (struct iriap_cb *) data; 948 949 IRDA_ASSERT(self != NULL, return;); 950 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 951 952 /* iriap_close(self); */ 953} 954 955#ifdef CONFIG_PROC_FS 956 957static const char *const ias_value_types[] = { 958 "IAS_MISSING", 959 "IAS_INTEGER", 960 "IAS_OCT_SEQ", 961 "IAS_STRING" 962}; 963 964static inline struct ias_object *irias_seq_idx(loff_t pos) 965{ 966 struct ias_object *obj; 967 968 for (obj = (struct ias_object *) hashbin_get_first(irias_objects); 969 obj; obj = (struct ias_object *) hashbin_get_next(irias_objects)) { 970 if (pos-- == 0) 971 break; 972 } 973 974 return obj; 975} 976 977static void *irias_seq_start(struct seq_file *seq, loff_t *pos) 978{ 979 spin_lock_irq(&irias_objects->hb_spinlock); 980 981 return *pos ? irias_seq_idx(*pos - 1) : SEQ_START_TOKEN; 982} 983 984static void *irias_seq_next(struct seq_file *seq, void *v, loff_t *pos) 985{ 986 ++*pos; 987 988 return (v == SEQ_START_TOKEN) 989 ? (void *) hashbin_get_first(irias_objects) 990 : (void *) hashbin_get_next(irias_objects); 991} 992 993static void irias_seq_stop(struct seq_file *seq, void *v) 994{ 995 spin_unlock_irq(&irias_objects->hb_spinlock); 996} 997 998static int irias_seq_show(struct seq_file *seq, void *v) 999{ 1000 if (v == SEQ_START_TOKEN) 1001 seq_puts(seq, "LM-IAS Objects:\n"); 1002 else { 1003 struct ias_object *obj = v; 1004 struct ias_attrib *attrib; 1005 1006 IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -EINVAL;); 1007 1008 seq_printf(seq, "name: %s, id=%d\n", 1009 obj->name, obj->id); 1010 1011 /* Careful for priority inversions here ! 1012 * All other uses of attrib spinlock are independent of 1013 * the object spinlock, so we are safe. Jean II */ 1014 spin_lock(&obj->attribs->hb_spinlock); 1015 1016 /* List all attributes for this object */ 1017 for (attrib = (struct ias_attrib *) hashbin_get_first(obj->attribs); 1018 attrib != NULL; 1019 attrib = (struct ias_attrib *) hashbin_get_next(obj->attribs)) { 1020 1021 IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, 1022 goto outloop; ); 1023 1024 seq_printf(seq, " - Attribute name: \"%s\", ", 1025 attrib->name); 1026 seq_printf(seq, "value[%s]: ", 1027 ias_value_types[attrib->value->type]); 1028 1029 switch (attrib->value->type) { 1030 case IAS_INTEGER: 1031 seq_printf(seq, "%d\n", 1032 attrib->value->t.integer); 1033 break; 1034 case IAS_STRING: 1035 seq_printf(seq, "\"%s\"\n", 1036 attrib->value->t.string); 1037 break; 1038 case IAS_OCT_SEQ: 1039 seq_printf(seq, "octet sequence (%d bytes)\n", 1040 attrib->value->len); 1041 break; 1042 case IAS_MISSING: 1043 seq_puts(seq, "missing\n"); 1044 break; 1045 default: 1046 seq_printf(seq, "type %d?\n", 1047 attrib->value->type); 1048 } 1049 seq_putc(seq, '\n'); 1050 1051 } 1052 IRDA_ASSERT_LABEL(outloop:) 1053 spin_unlock(&obj->attribs->hb_spinlock); 1054 } 1055 1056 return 0; 1057} 1058 1059static const struct seq_operations irias_seq_ops = { 1060 .start = irias_seq_start, 1061 .next = irias_seq_next, 1062 .stop = irias_seq_stop, 1063 .show = irias_seq_show, 1064}; 1065 1066static int irias_seq_open(struct inode *inode, struct file *file) 1067{ 1068 IRDA_ASSERT( irias_objects != NULL, return -EINVAL;); 1069 1070 return seq_open(file, &irias_seq_ops); 1071} 1072 1073const struct file_operations irias_seq_fops = { 1074 .owner = THIS_MODULE, 1075 .open = irias_seq_open, 1076 .read = seq_read, 1077 .llseek = seq_lseek, 1078 .release = seq_release, 1079}; 1080 1081#endif /* PROC_FS */ 1082