irlan_common.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. /*********************************************************************
  2. *
  3. * Filename: irlan_common.c
  4. * Version: 0.9
  5. * Description: IrDA LAN Access Protocol Implementation
  6. * Status: Experimental.
  7. * Author: Dag Brattli <dagb@cs.uit.no>
  8. * Created at: Sun Aug 31 20:14:37 1997
  9. * Modified at: Sun Dec 26 21:53:10 1999
  10. * Modified by: Dag Brattli <dagb@cs.uit.no>
  11. *
  12. * Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
  13. * All Rights Reserved.
  14. *
  15. * This program is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU General Public License as
  17. * published by the Free Software Foundation; either version 2 of
  18. * the License, or (at your option) any later version.
  19. *
  20. * Neither Dag Brattli nor University of Tromsø admit liability nor
  21. * provide warranty for any of this software. This material is
  22. * provided "AS-IS" and at no charge.
  23. *
  24. ********************************************************************/
  25. #include <linux/module.h>
  26. #include <linux/kernel.h>
  27. #include <linux/string.h>
  28. #include <linux/init.h>
  29. #include <linux/errno.h>
  30. #include <linux/proc_fs.h>
  31. #include <linux/seq_file.h>
  32. #include <linux/random.h>
  33. #include <linux/netdevice.h>
  34. #include <linux/etherdevice.h>
  35. #include <linux/rtnetlink.h>
  36. #include <linux/moduleparam.h>
  37. #include <linux/bitops.h>
  38. #include <asm/system.h>
  39. #include <asm/byteorder.h>
  40. #include <net/irda/irda.h>
  41. #include <net/irda/irttp.h>
  42. #include <net/irda/irlmp.h>
  43. #include <net/irda/iriap.h>
  44. #include <net/irda/timer.h>
  45. #include <net/irda/irlan_common.h>
  46. #include <net/irda/irlan_client.h>
  47. #include <net/irda/irlan_provider.h>
  48. #include <net/irda/irlan_eth.h>
  49. #include <net/irda/irlan_filter.h>
  50. /*
  51. * Send gratuitous ARP when connected to a new AP or not. May be a clever
  52. * thing to do, but for some reason the machine crashes if you use DHCP. So
  53. * lets not use it by default.
  54. */
  55. #undef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
  56. /* extern char sysctl_devname[]; */
  57. /*
  58. * Master structure
  59. */
  60. static LIST_HEAD(irlans);
  61. static void *ckey;
  62. static void *skey;
  63. /* Module parameters */
  64. static int eth; /* Use "eth" or "irlan" name for devices */
  65. static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */
  66. #ifdef CONFIG_PROC_FS
  67. static const char *irlan_access[] = {
  68. "UNKNOWN",
  69. "DIRECT",
  70. "PEER",
  71. "HOSTED"
  72. };
  73. static const char *irlan_media[] = {
  74. "UNKNOWN",
  75. "802.3",
  76. "802.5"
  77. };
  78. extern struct proc_dir_entry *proc_irda;
  79. static int irlan_seq_open(struct inode *inode, struct file *file);
  80. static const struct file_operations irlan_fops = {
  81. .owner = THIS_MODULE,
  82. .open = irlan_seq_open,
  83. .read = seq_read,
  84. .llseek = seq_lseek,
  85. .release = seq_release,
  86. };
  87. extern struct proc_dir_entry *proc_irda;
  88. #endif /* CONFIG_PROC_FS */
  89. static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr);
  90. static void __irlan_close(struct irlan_cb *self);
  91. static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
  92. __u8 value_byte, __u16 value_short,
  93. __u8 *value_array, __u16 value_len);
  94. static void irlan_open_unicast_addr(struct irlan_cb *self);
  95. static void irlan_get_unicast_addr(struct irlan_cb *self);
  96. void irlan_close_tsaps(struct irlan_cb *self);
  97. /*
  98. * Function irlan_init (void)
  99. *
  100. * Initialize IrLAN layer
  101. *
  102. */
  103. static int __init irlan_init(void)
  104. {
  105. struct irlan_cb *new;
  106. __u16 hints;
  107. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  108. #ifdef CONFIG_PROC_FS
  109. { struct proc_dir_entry *proc;
  110. proc = proc_create("irlan", 0, proc_irda, &irlan_fops);
  111. if (!proc) {
  112. printk(KERN_ERR "irlan_init: can't create /proc entry!\n");
  113. return -ENODEV;
  114. }
  115. }
  116. #endif /* CONFIG_PROC_FS */
  117. IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
  118. hints = irlmp_service_to_hint(S_LAN);
  119. /* Register with IrLMP as a client */
  120. ckey = irlmp_register_client(hints, &irlan_client_discovery_indication,
  121. NULL, NULL);
  122. if (!ckey)
  123. goto err_ckey;
  124. /* Register with IrLMP as a service */
  125. skey = irlmp_register_service(hints);
  126. if (!skey)
  127. goto err_skey;
  128. /* Start the master IrLAN instance (the only one for now) */
  129. new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY);
  130. if (!new)
  131. goto err_open;
  132. /* The master will only open its (listen) control TSAP */
  133. irlan_provider_open_ctrl_tsap(new);
  134. /* Do some fast discovery! */
  135. irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
  136. return 0;
  137. err_open:
  138. irlmp_unregister_service(skey);
  139. err_skey:
  140. irlmp_unregister_client(ckey);
  141. err_ckey:
  142. #ifdef CONFIG_PROC_FS
  143. remove_proc_entry("irlan", proc_irda);
  144. #endif /* CONFIG_PROC_FS */
  145. return -ENOMEM;
  146. }
  147. static void __exit irlan_cleanup(void)
  148. {
  149. struct irlan_cb *self, *next;
  150. IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
  151. irlmp_unregister_client(ckey);
  152. irlmp_unregister_service(skey);
  153. #ifdef CONFIG_PROC_FS
  154. remove_proc_entry("irlan", proc_irda);
  155. #endif /* CONFIG_PROC_FS */
  156. /* Cleanup any leftover network devices */
  157. rtnl_lock();
  158. list_for_each_entry_safe(self, next, &irlans, dev_list) {
  159. __irlan_close(self);
  160. }
  161. rtnl_unlock();
  162. }
  163. /*
  164. * Function irlan_open (void)
  165. *
  166. * Open new instance of a client/provider, we should only register the
  167. * network device if this instance is ment for a particular client/provider
  168. */
  169. static struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
  170. {
  171. struct net_device *dev;
  172. struct irlan_cb *self;
  173. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  174. /* Create network device with irlan */
  175. dev = alloc_irlandev(eth ? "eth%d" : "irlan%d");
  176. if (!dev)
  177. return NULL;
  178. self = dev->priv;
  179. self->dev = dev;
  180. /*
  181. * Initialize local device structure
  182. */
  183. self->magic = IRLAN_MAGIC;
  184. self->saddr = saddr;
  185. self->daddr = daddr;
  186. /* Provider access can only be PEER, DIRECT, or HOSTED */
  187. self->provider.access_type = access;
  188. if (access == ACCESS_DIRECT) {
  189. /*
  190. * Since we are emulating an IrLAN sever we will have to
  191. * give ourself an ethernet address!
  192. */
  193. dev->dev_addr[0] = 0x40;
  194. dev->dev_addr[1] = 0x00;
  195. dev->dev_addr[2] = 0x00;
  196. dev->dev_addr[3] = 0x00;
  197. get_random_bytes(dev->dev_addr+4, 1);
  198. get_random_bytes(dev->dev_addr+5, 1);
  199. }
  200. self->media = MEDIA_802_3;
  201. self->disconnect_reason = LM_USER_REQUEST;
  202. init_timer(&self->watchdog_timer);
  203. init_timer(&self->client.kick_timer);
  204. init_waitqueue_head(&self->open_wait);
  205. skb_queue_head_init(&self->client.txq);
  206. irlan_next_client_state(self, IRLAN_IDLE);
  207. irlan_next_provider_state(self, IRLAN_IDLE);
  208. if (register_netdev(dev)) {
  209. IRDA_DEBUG(2, "%s(), register_netdev() failed!\n",
  210. __FUNCTION__ );
  211. self = NULL;
  212. free_netdev(dev);
  213. } else {
  214. rtnl_lock();
  215. list_add_rcu(&self->dev_list, &irlans);
  216. rtnl_unlock();
  217. }
  218. return self;
  219. }
  220. /*
  221. * Function __irlan_close (self)
  222. *
  223. * This function closes and deallocates the IrLAN client instances. Be
  224. * aware that other functions which calls client_close() must
  225. * remove self from irlans list first.
  226. */
  227. static void __irlan_close(struct irlan_cb *self)
  228. {
  229. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  230. ASSERT_RTNL();
  231. IRDA_ASSERT(self != NULL, return;);
  232. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  233. del_timer_sync(&self->watchdog_timer);
  234. del_timer_sync(&self->client.kick_timer);
  235. /* Close all open connections and remove TSAPs */
  236. irlan_close_tsaps(self);
  237. if (self->client.iriap)
  238. iriap_close(self->client.iriap);
  239. /* Remove frames queued on the control channel */
  240. skb_queue_purge(&self->client.txq);
  241. /* Unregister and free self via destructor */
  242. unregister_netdevice(self->dev);
  243. }
  244. /* Find any instance of irlan, used for client discovery wakeup */
  245. struct irlan_cb *irlan_get_any(void)
  246. {
  247. struct irlan_cb *self;
  248. list_for_each_entry_rcu(self, &irlans, dev_list) {
  249. return self;
  250. }
  251. return NULL;
  252. }
  253. /*
  254. * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb)
  255. *
  256. * Here we receive the connect indication for the data channel
  257. *
  258. */
  259. static void irlan_connect_indication(void *instance, void *sap,
  260. struct qos_info *qos,
  261. __u32 max_sdu_size,
  262. __u8 max_header_size,
  263. struct sk_buff *skb)
  264. {
  265. struct irlan_cb *self;
  266. struct tsap_cb *tsap;
  267. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  268. self = (struct irlan_cb *) instance;
  269. tsap = (struct tsap_cb *) sap;
  270. IRDA_ASSERT(self != NULL, return;);
  271. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  272. IRDA_ASSERT(tsap == self->tsap_data,return;);
  273. self->max_sdu_size = max_sdu_size;
  274. self->max_header_size = max_header_size;
  275. IRDA_DEBUG(0, "%s: We are now connected!\n", __FUNCTION__);
  276. del_timer(&self->watchdog_timer);
  277. /* If you want to pass the skb to *both* state machines, you will
  278. * need to skb_clone() it, so that you don't free it twice.
  279. * As the state machines don't need it, git rid of it here...
  280. * Jean II */
  281. if (skb)
  282. dev_kfree_skb(skb);
  283. irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, NULL);
  284. irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, NULL);
  285. if (self->provider.access_type == ACCESS_PEER) {
  286. /*
  287. * Data channel is open, so we are now allowed to
  288. * configure the remote filter
  289. */
  290. irlan_get_unicast_addr(self);
  291. irlan_open_unicast_addr(self);
  292. }
  293. /* Ready to transfer Ethernet frames (at last) */
  294. netif_start_queue(self->dev); /* Clear reason */
  295. }
  296. static void irlan_connect_confirm(void *instance, void *sap,
  297. struct qos_info *qos,
  298. __u32 max_sdu_size,
  299. __u8 max_header_size,
  300. struct sk_buff *skb)
  301. {
  302. struct irlan_cb *self;
  303. self = (struct irlan_cb *) instance;
  304. IRDA_ASSERT(self != NULL, return;);
  305. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  306. self->max_sdu_size = max_sdu_size;
  307. self->max_header_size = max_header_size;
  308. /* TODO: we could set the MTU depending on the max_sdu_size */
  309. IRDA_DEBUG(0, "%s: We are now connected!\n", __FUNCTION__);
  310. del_timer(&self->watchdog_timer);
  311. /*
  312. * Data channel is open, so we are now allowed to configure the remote
  313. * filter
  314. */
  315. irlan_get_unicast_addr(self);
  316. irlan_open_unicast_addr(self);
  317. /* Open broadcast and multicast filter by default */
  318. irlan_set_broadcast_filter(self, TRUE);
  319. irlan_set_multicast_filter(self, TRUE);
  320. /* Ready to transfer Ethernet frames */
  321. netif_start_queue(self->dev);
  322. self->disconnect_reason = 0; /* Clear reason */
  323. #ifdef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
  324. irlan_eth_send_gratuitous_arp(&self->dev);
  325. #endif
  326. wake_up_interruptible(&self->open_wait);
  327. }
  328. /*
  329. * Function irlan_client_disconnect_indication (handle)
  330. *
  331. * Callback function for the IrTTP layer. Indicates a disconnection of
  332. * the specified connection (handle)
  333. */
  334. static void irlan_disconnect_indication(void *instance,
  335. void *sap, LM_REASON reason,
  336. struct sk_buff *userdata)
  337. {
  338. struct irlan_cb *self;
  339. struct tsap_cb *tsap;
  340. IRDA_DEBUG(0, "%s(), reason=%d\n", __FUNCTION__ , reason);
  341. self = (struct irlan_cb *) instance;
  342. tsap = (struct tsap_cb *) sap;
  343. IRDA_ASSERT(self != NULL, return;);
  344. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  345. IRDA_ASSERT(tsap != NULL, return;);
  346. IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
  347. IRDA_ASSERT(tsap == self->tsap_data, return;);
  348. IRDA_DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
  349. /* Save reason so we know if we should try to reconnect or not */
  350. self->disconnect_reason = reason;
  351. switch (reason) {
  352. case LM_USER_REQUEST: /* User request */
  353. IRDA_DEBUG(2, "%s(), User requested\n", __FUNCTION__ );
  354. break;
  355. case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
  356. IRDA_DEBUG(2, "%s(), Unexpected IrLAP disconnect\n", __FUNCTION__ );
  357. break;
  358. case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */
  359. IRDA_DEBUG(2, "%s(), IrLAP connect failed\n", __FUNCTION__ );
  360. break;
  361. case LM_LAP_RESET: /* IrLAP reset */
  362. IRDA_DEBUG(2, "%s(), IrLAP reset\n", __FUNCTION__ );
  363. break;
  364. case LM_INIT_DISCONNECT:
  365. IRDA_DEBUG(2, "%s(), IrLMP connect failed\n", __FUNCTION__ );
  366. break;
  367. default:
  368. IRDA_ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);
  369. break;
  370. }
  371. /* If you want to pass the skb to *both* state machines, you will
  372. * need to skb_clone() it, so that you don't free it twice.
  373. * As the state machines don't need it, git rid of it here...
  374. * Jean II */
  375. if (userdata)
  376. dev_kfree_skb(userdata);
  377. irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
  378. irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
  379. wake_up_interruptible(&self->open_wait);
  380. }
  381. void irlan_open_data_tsap(struct irlan_cb *self)
  382. {
  383. struct tsap_cb *tsap;
  384. notify_t notify;
  385. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  386. IRDA_ASSERT(self != NULL, return;);
  387. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  388. /* Check if already open */
  389. if (self->tsap_data)
  390. return;
  391. irda_notify_init(&notify);
  392. notify.data_indication = irlan_eth_receive;
  393. notify.udata_indication = irlan_eth_receive;
  394. notify.connect_indication = irlan_connect_indication;
  395. notify.connect_confirm = irlan_connect_confirm;
  396. notify.flow_indication = irlan_eth_flow_indication;
  397. notify.disconnect_indication = irlan_disconnect_indication;
  398. notify.instance = self;
  399. strlcpy(notify.name, "IrLAN data", sizeof(notify.name));
  400. tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
  401. if (!tsap) {
  402. IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );
  403. return;
  404. }
  405. self->tsap_data = tsap;
  406. /*
  407. * This is the data TSAP selector which we will pass to the client
  408. * when the client ask for it.
  409. */
  410. self->stsap_sel_data = self->tsap_data->stsap_sel;
  411. }
  412. void irlan_close_tsaps(struct irlan_cb *self)
  413. {
  414. IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
  415. IRDA_ASSERT(self != NULL, return;);
  416. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  417. /* Disconnect and close all open TSAP connections */
  418. if (self->tsap_data) {
  419. irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);
  420. irttp_close_tsap(self->tsap_data);
  421. self->tsap_data = NULL;
  422. }
  423. if (self->client.tsap_ctrl) {
  424. irttp_disconnect_request(self->client.tsap_ctrl, NULL,
  425. P_NORMAL);
  426. irttp_close_tsap(self->client.tsap_ctrl);
  427. self->client.tsap_ctrl = NULL;
  428. }
  429. if (self->provider.tsap_ctrl) {
  430. irttp_disconnect_request(self->provider.tsap_ctrl, NULL,
  431. P_NORMAL);
  432. irttp_close_tsap(self->provider.tsap_ctrl);
  433. self->provider.tsap_ctrl = NULL;
  434. }
  435. self->disconnect_reason = LM_USER_REQUEST;
  436. }
  437. /*
  438. * Function irlan_ias_register (self, tsap_sel)
  439. *
  440. * Register with LM-IAS
  441. *
  442. */
  443. void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel)
  444. {
  445. struct ias_object *obj;
  446. struct ias_value *new_value;
  447. IRDA_ASSERT(self != NULL, return;);
  448. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  449. /*
  450. * Check if object has already been registered by a previous provider.
  451. * If that is the case, we just change the value of the attribute
  452. */
  453. if (!irias_find_object("IrLAN")) {
  454. obj = irias_new_object("IrLAN", IAS_IRLAN_ID);
  455. irias_add_integer_attrib(obj, "IrDA:TinyTP:LsapSel", tsap_sel,
  456. IAS_KERNEL_ATTR);
  457. irias_insert_object(obj);
  458. } else {
  459. new_value = irias_new_integer_value(tsap_sel);
  460. irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
  461. new_value);
  462. }
  463. /* Register PnP object only if not registered before */
  464. if (!irias_find_object("PnP")) {
  465. obj = irias_new_object("PnP", IAS_PNP_ID);
  466. #if 0
  467. irias_add_string_attrib(obj, "Name", sysctl_devname,
  468. IAS_KERNEL_ATTR);
  469. #else
  470. irias_add_string_attrib(obj, "Name", "Linux", IAS_KERNEL_ATTR);
  471. #endif
  472. irias_add_string_attrib(obj, "DeviceID", "HWP19F0",
  473. IAS_KERNEL_ATTR);
  474. irias_add_integer_attrib(obj, "CompCnt", 1, IAS_KERNEL_ATTR);
  475. if (self->provider.access_type == ACCESS_PEER)
  476. irias_add_string_attrib(obj, "Comp#01", "PNP8389",
  477. IAS_KERNEL_ATTR);
  478. else
  479. irias_add_string_attrib(obj, "Comp#01", "PNP8294",
  480. IAS_KERNEL_ATTR);
  481. irias_add_string_attrib(obj, "Manufacturer",
  482. "Linux-IrDA Project", IAS_KERNEL_ATTR);
  483. irias_insert_object(obj);
  484. }
  485. }
  486. /*
  487. * Function irlan_run_ctrl_tx_queue (self)
  488. *
  489. * Try to send the next command in the control transmit queue
  490. *
  491. */
  492. int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
  493. {
  494. struct sk_buff *skb;
  495. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  496. if (irda_lock(&self->client.tx_busy) == FALSE)
  497. return -EBUSY;
  498. skb = skb_dequeue(&self->client.txq);
  499. if (!skb) {
  500. self->client.tx_busy = FALSE;
  501. return 0;
  502. }
  503. /* Check that it's really possible to send commands */
  504. if ((self->client.tsap_ctrl == NULL) ||
  505. (self->client.state == IRLAN_IDLE))
  506. {
  507. self->client.tx_busy = FALSE;
  508. dev_kfree_skb(skb);
  509. return -1;
  510. }
  511. IRDA_DEBUG(2, "%s(), sending ...\n", __FUNCTION__ );
  512. return irttp_data_request(self->client.tsap_ctrl, skb);
  513. }
  514. /*
  515. * Function irlan_ctrl_data_request (self, skb)
  516. *
  517. * This function makes sure that commands on the control channel is being
  518. * sent in a command/response fashion
  519. */
  520. static void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb)
  521. {
  522. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  523. /* Queue command */
  524. skb_queue_tail(&self->client.txq, skb);
  525. /* Try to send command */
  526. irlan_run_ctrl_tx_queue(self);
  527. }
  528. /*
  529. * Function irlan_get_provider_info (self)
  530. *
  531. * Send Get Provider Information command to peer IrLAN layer
  532. *
  533. */
  534. void irlan_get_provider_info(struct irlan_cb *self)
  535. {
  536. struct sk_buff *skb;
  537. __u8 *frame;
  538. IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
  539. IRDA_ASSERT(self != NULL, return;);
  540. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  541. skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER,
  542. GFP_ATOMIC);
  543. if (!skb)
  544. return;
  545. /* Reserve space for TTP, LMP, and LAP header */
  546. skb_reserve(skb, self->client.max_header_size);
  547. skb_put(skb, 2);
  548. frame = skb->data;
  549. frame[0] = CMD_GET_PROVIDER_INFO;
  550. frame[1] = 0x00; /* Zero parameters */
  551. irlan_ctrl_data_request(self, skb);
  552. }
  553. /*
  554. * Function irlan_open_data_channel (self)
  555. *
  556. * Send an Open Data Command to provider
  557. *
  558. */
  559. void irlan_open_data_channel(struct irlan_cb *self)
  560. {
  561. struct sk_buff *skb;
  562. __u8 *frame;
  563. IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
  564. IRDA_ASSERT(self != NULL, return;);
  565. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  566. skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
  567. IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3") +
  568. IRLAN_STRING_PARAMETER_LEN("ACCESS_TYPE", "DIRECT"),
  569. GFP_ATOMIC);
  570. if (!skb)
  571. return;
  572. skb_reserve(skb, self->client.max_header_size);
  573. skb_put(skb, 2);
  574. frame = skb->data;
  575. /* Build frame */
  576. frame[0] = CMD_OPEN_DATA_CHANNEL;
  577. frame[1] = 0x02; /* Two parameters */
  578. irlan_insert_string_param(skb, "MEDIA", "802.3");
  579. irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
  580. /* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); */
  581. /* self->use_udata = TRUE; */
  582. irlan_ctrl_data_request(self, skb);
  583. }
  584. void irlan_close_data_channel(struct irlan_cb *self)
  585. {
  586. struct sk_buff *skb;
  587. __u8 *frame;
  588. IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
  589. IRDA_ASSERT(self != NULL, return;);
  590. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  591. /* Check if the TSAP is still there */
  592. if (self->client.tsap_ctrl == NULL)
  593. return;
  594. skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
  595. IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN"),
  596. GFP_ATOMIC);
  597. if (!skb)
  598. return;
  599. skb_reserve(skb, self->client.max_header_size);
  600. skb_put(skb, 2);
  601. frame = skb->data;
  602. /* Build frame */
  603. frame[0] = CMD_CLOSE_DATA_CHAN;
  604. frame[1] = 0x01; /* One parameter */
  605. irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
  606. irlan_ctrl_data_request(self, skb);
  607. }
  608. /*
  609. * Function irlan_open_unicast_addr (self)
  610. *
  611. * Make IrLAN provider accept ethernet frames addressed to the unicast
  612. * address.
  613. *
  614. */
  615. static void irlan_open_unicast_addr(struct irlan_cb *self)
  616. {
  617. struct sk_buff *skb;
  618. __u8 *frame;
  619. IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
  620. IRDA_ASSERT(self != NULL, return;);
  621. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  622. skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
  623. IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
  624. IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
  625. IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),
  626. GFP_ATOMIC);
  627. if (!skb)
  628. return;
  629. /* Reserve space for TTP, LMP, and LAP header */
  630. skb_reserve(skb, self->max_header_size);
  631. skb_put(skb, 2);
  632. frame = skb->data;
  633. frame[0] = CMD_FILTER_OPERATION;
  634. frame[1] = 0x03; /* Three parameters */
  635. irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
  636. irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
  637. irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
  638. irlan_ctrl_data_request(self, skb);
  639. }
  640. /*
  641. * Function irlan_set_broadcast_filter (self, status)
  642. *
  643. * Make IrLAN provider accept ethernet frames addressed to the broadcast
  644. * address. Be careful with the use of this one, since there may be a lot
  645. * of broadcast traffic out there. We can still function without this
  646. * one but then _we_ have to initiate all communication with other
  647. * hosts, since ARP request for this host will not be answered.
  648. */
  649. void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
  650. {
  651. struct sk_buff *skb;
  652. __u8 *frame;
  653. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  654. IRDA_ASSERT(self != NULL, return;);
  655. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  656. skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
  657. IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
  658. IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BROADCAST") +
  659. /* We may waste one byte here...*/
  660. IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),
  661. GFP_ATOMIC);
  662. if (!skb)
  663. return;
  664. /* Reserve space for TTP, LMP, and LAP header */
  665. skb_reserve(skb, self->client.max_header_size);
  666. skb_put(skb, 2);
  667. frame = skb->data;
  668. frame[0] = CMD_FILTER_OPERATION;
  669. frame[1] = 0x03; /* Three parameters */
  670. irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
  671. irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
  672. if (status)
  673. irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
  674. else
  675. irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
  676. irlan_ctrl_data_request(self, skb);
  677. }
  678. /*
  679. * Function irlan_set_multicast_filter (self, status)
  680. *
  681. * Make IrLAN provider accept ethernet frames addressed to the multicast
  682. * address.
  683. *
  684. */
  685. void irlan_set_multicast_filter(struct irlan_cb *self, int status)
  686. {
  687. struct sk_buff *skb;
  688. __u8 *frame;
  689. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  690. IRDA_ASSERT(self != NULL, return;);
  691. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  692. skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
  693. IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
  694. IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "MULTICAST") +
  695. /* We may waste one byte here...*/
  696. IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "NONE"),
  697. GFP_ATOMIC);
  698. if (!skb)
  699. return;
  700. /* Reserve space for TTP, LMP, and LAP header */
  701. skb_reserve(skb, self->client.max_header_size);
  702. skb_put(skb, 2);
  703. frame = skb->data;
  704. frame[0] = CMD_FILTER_OPERATION;
  705. frame[1] = 0x03; /* Three parameters */
  706. irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
  707. irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
  708. if (status)
  709. irlan_insert_string_param(skb, "FILTER_MODE", "ALL");
  710. else
  711. irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
  712. irlan_ctrl_data_request(self, skb);
  713. }
  714. /*
  715. * Function irlan_get_unicast_addr (self)
  716. *
  717. * Retrieves the unicast address from the IrLAN provider. This address
  718. * will be inserted into the devices structure, so the ethernet layer
  719. * can construct its packets.
  720. *
  721. */
  722. static void irlan_get_unicast_addr(struct irlan_cb *self)
  723. {
  724. struct sk_buff *skb;
  725. __u8 *frame;
  726. IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
  727. IRDA_ASSERT(self != NULL, return;);
  728. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  729. skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
  730. IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
  731. IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
  732. IRLAN_STRING_PARAMETER_LEN("FILTER_OPERATION",
  733. "DYNAMIC"),
  734. GFP_ATOMIC);
  735. if (!skb)
  736. return;
  737. /* Reserve space for TTP, LMP, and LAP header */
  738. skb_reserve(skb, self->client.max_header_size);
  739. skb_put(skb, 2);
  740. frame = skb->data;
  741. frame[0] = CMD_FILTER_OPERATION;
  742. frame[1] = 0x03; /* Three parameters */
  743. irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
  744. irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
  745. irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC");
  746. irlan_ctrl_data_request(self, skb);
  747. }
  748. /*
  749. * Function irlan_get_media_char (self)
  750. *
  751. *
  752. *
  753. */
  754. void irlan_get_media_char(struct irlan_cb *self)
  755. {
  756. struct sk_buff *skb;
  757. __u8 *frame;
  758. IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
  759. IRDA_ASSERT(self != NULL, return;);
  760. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  761. skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +
  762. IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3"),
  763. GFP_ATOMIC);
  764. if (!skb)
  765. return;
  766. /* Reserve space for TTP, LMP, and LAP header */
  767. skb_reserve(skb, self->client.max_header_size);
  768. skb_put(skb, 2);
  769. frame = skb->data;
  770. /* Build frame */
  771. frame[0] = CMD_GET_MEDIA_CHAR;
  772. frame[1] = 0x01; /* One parameter */
  773. irlan_insert_string_param(skb, "MEDIA", "802.3");
  774. irlan_ctrl_data_request(self, skb);
  775. }
  776. /*
  777. * Function insert_byte_param (skb, param, value)
  778. *
  779. * Insert byte parameter into frame
  780. *
  781. */
  782. int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value)
  783. {
  784. return __irlan_insert_param(skb, param, IRLAN_BYTE, value, 0, NULL, 0);
  785. }
  786. int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value)
  787. {
  788. return __irlan_insert_param(skb, param, IRLAN_SHORT, 0, value, NULL, 0);
  789. }
  790. /*
  791. * Function insert_string (skb, param, value)
  792. *
  793. * Insert string parameter into frame
  794. *
  795. */
  796. int irlan_insert_string_param(struct sk_buff *skb, char *param, char *string)
  797. {
  798. int string_len = strlen(string);
  799. return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string,
  800. string_len);
  801. }
  802. /*
  803. * Function insert_array_param(skb, param, value, len_value)
  804. *
  805. * Insert array parameter into frame
  806. *
  807. */
  808. int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array,
  809. __u16 array_len)
  810. {
  811. return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array,
  812. array_len);
  813. }
  814. /*
  815. * Function insert_param (skb, param, value, byte)
  816. *
  817. * Insert parameter at end of buffer, structure of a parameter is:
  818. *
  819. * -----------------------------------------------------------------------
  820. * | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
  821. * -----------------------------------------------------------------------
  822. */
  823. static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
  824. __u8 value_byte, __u16 value_short,
  825. __u8 *value_array, __u16 value_len)
  826. {
  827. __u8 *frame;
  828. __u8 param_len;
  829. __le16 tmp_le; /* Temporary value in little endian format */
  830. int n=0;
  831. if (skb == NULL) {
  832. IRDA_DEBUG(2, "%s(), Got NULL skb\n", __FUNCTION__ );
  833. return 0;
  834. }
  835. param_len = strlen(param);
  836. switch (type) {
  837. case IRLAN_BYTE:
  838. value_len = 1;
  839. break;
  840. case IRLAN_SHORT:
  841. value_len = 2;
  842. break;
  843. case IRLAN_ARRAY:
  844. IRDA_ASSERT(value_array != NULL, return 0;);
  845. IRDA_ASSERT(value_len > 0, return 0;);
  846. break;
  847. default:
  848. IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __FUNCTION__ );
  849. return 0;
  850. break;
  851. }
  852. /* Insert at end of sk-buffer */
  853. frame = skb_tail_pointer(skb);
  854. /* Make space for data */
  855. if (skb_tailroom(skb) < (param_len+value_len+3)) {
  856. IRDA_DEBUG(2, "%s(), No more space at end of skb\n", __FUNCTION__ );
  857. return 0;
  858. }
  859. skb_put(skb, param_len+value_len+3);
  860. /* Insert parameter length */
  861. frame[n++] = param_len;
  862. /* Insert parameter */
  863. memcpy(frame+n, param, param_len); n += param_len;
  864. /* Insert value length (2 byte little endian format, LSB first) */
  865. tmp_le = cpu_to_le16(value_len);
  866. memcpy(frame+n, &tmp_le, 2); n += 2; /* To avoid alignment problems */
  867. /* Insert value */
  868. switch (type) {
  869. case IRLAN_BYTE:
  870. frame[n++] = value_byte;
  871. break;
  872. case IRLAN_SHORT:
  873. tmp_le = cpu_to_le16(value_short);
  874. memcpy(frame+n, &tmp_le, 2); n += 2;
  875. break;
  876. case IRLAN_ARRAY:
  877. memcpy(frame+n, value_array, value_len); n+=value_len;
  878. break;
  879. default:
  880. break;
  881. }
  882. IRDA_ASSERT(n == (param_len+value_len+3), return 0;);
  883. return param_len+value_len+3;
  884. }
  885. /*
  886. * Function irlan_extract_param (buf, name, value, len)
  887. *
  888. * Extracts a single parameter name/value pair from buffer and updates
  889. * the buffer pointer to point to the next name/value pair.
  890. */
  891. int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
  892. {
  893. __u8 name_len;
  894. __u16 val_len;
  895. int n=0;
  896. IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
  897. /* get length of parameter name (1 byte) */
  898. name_len = buf[n++];
  899. if (name_len > 254) {
  900. IRDA_DEBUG(2, "%s(), name_len > 254\n", __FUNCTION__ );
  901. return -RSP_INVALID_COMMAND_FORMAT;
  902. }
  903. /* get parameter name */
  904. memcpy(name, buf+n, name_len);
  905. name[name_len] = '\0';
  906. n+=name_len;
  907. /*
  908. * Get length of parameter value (2 bytes in little endian
  909. * format)
  910. */
  911. memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
  912. le16_to_cpus(&val_len); n+=2;
  913. if (val_len > 1016) {
  914. IRDA_DEBUG(2, "%s(), parameter length to long\n", __FUNCTION__ );
  915. return -RSP_INVALID_COMMAND_FORMAT;
  916. }
  917. *len = val_len;
  918. /* get parameter value */
  919. memcpy(value, buf+n, val_len);
  920. value[val_len] = '\0';
  921. n+=val_len;
  922. IRDA_DEBUG(4, "Parameter: %s ", name);
  923. IRDA_DEBUG(4, "Value: %s\n", value);
  924. return n;
  925. }
  926. #ifdef CONFIG_PROC_FS
  927. /*
  928. * Start of reading /proc entries.
  929. * Return entry at pos,
  930. * or start_token to indicate print header line
  931. * or NULL if end of file
  932. */
  933. static void *irlan_seq_start(struct seq_file *seq, loff_t *pos)
  934. {
  935. int i = 1;
  936. struct irlan_cb *self;
  937. rcu_read_lock();
  938. if (*pos == 0)
  939. return SEQ_START_TOKEN;
  940. list_for_each_entry(self, &irlans, dev_list) {
  941. if (*pos == i)
  942. return self;
  943. ++i;
  944. }
  945. return NULL;
  946. }
  947. /* Return entry after v, and increment pos */
  948. static void *irlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  949. {
  950. struct list_head *nxt;
  951. ++*pos;
  952. if (v == SEQ_START_TOKEN)
  953. nxt = irlans.next;
  954. else
  955. nxt = ((struct irlan_cb *)v)->dev_list.next;
  956. return (nxt == &irlans) ? NULL
  957. : list_entry(nxt, struct irlan_cb, dev_list);
  958. }
  959. /* End of reading /proc file */
  960. static void irlan_seq_stop(struct seq_file *seq, void *v)
  961. {
  962. rcu_read_unlock();
  963. }
  964. /*
  965. * Show one entry in /proc file.
  966. */
  967. static int irlan_seq_show(struct seq_file *seq, void *v)
  968. {
  969. if (v == SEQ_START_TOKEN)
  970. seq_puts(seq, "IrLAN instances:\n");
  971. else {
  972. struct irlan_cb *self = v;
  973. IRDA_ASSERT(self != NULL, return -1;);
  974. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
  975. seq_printf(seq,"ifname: %s,\n",
  976. self->dev->name);
  977. seq_printf(seq,"client state: %s, ",
  978. irlan_state[ self->client.state]);
  979. seq_printf(seq,"provider state: %s,\n",
  980. irlan_state[ self->provider.state]);
  981. seq_printf(seq,"saddr: %#08x, ",
  982. self->saddr);
  983. seq_printf(seq,"daddr: %#08x\n",
  984. self->daddr);
  985. seq_printf(seq,"version: %d.%d,\n",
  986. self->version[1], self->version[0]);
  987. seq_printf(seq,"access type: %s\n",
  988. irlan_access[self->client.access_type]);
  989. seq_printf(seq,"media: %s\n",
  990. irlan_media[self->media]);
  991. seq_printf(seq,"local filter:\n");
  992. seq_printf(seq,"remote filter: ");
  993. irlan_print_filter(seq, self->client.filter_type);
  994. seq_printf(seq,"tx busy: %s\n",
  995. netif_queue_stopped(self->dev) ? "TRUE" : "FALSE");
  996. seq_putc(seq,'\n');
  997. }
  998. return 0;
  999. }
  1000. static const struct seq_operations irlan_seq_ops = {
  1001. .start = irlan_seq_start,
  1002. .next = irlan_seq_next,
  1003. .stop = irlan_seq_stop,
  1004. .show = irlan_seq_show,
  1005. };
  1006. static int irlan_seq_open(struct inode *inode, struct file *file)
  1007. {
  1008. return seq_open(file, &irlan_seq_ops);
  1009. }
  1010. #endif
  1011. MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
  1012. MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
  1013. MODULE_LICENSE("GPL");
  1014. module_param(eth, bool, 0);
  1015. MODULE_PARM_DESC(eth, "Name devices ethX (0) or irlanX (1)");
  1016. module_param(access, int, 0);
  1017. MODULE_PARM_DESC(access, "Access type DIRECT=1, PEER=2, HOSTED=3");
  1018. module_init(irlan_init);
  1019. module_exit(irlan_cleanup);