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