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