iriap.c 26 KB

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