ircomm_param.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /*********************************************************************
  2. *
  3. * Filename: ircomm_param.c
  4. * Version: 1.0
  5. * Description: Parameter handling for the IrCOMM protocol
  6. * Status: Experimental.
  7. * Author: Dag Brattli <dagb@cs.uit.no>
  8. * Created at: Mon Jun 7 10:25:11 1999
  9. * Modified at: Sun Jan 30 14:32:03 2000
  10. * Modified by: Dag Brattli <dagb@cs.uit.no>
  11. *
  12. * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License as
  16. * published by the Free Software Foundation; either version 2 of
  17. * the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  27. * MA 02111-1307 USA
  28. *
  29. ********************************************************************/
  30. #include <linux/gfp.h>
  31. #include <linux/workqueue.h>
  32. #include <linux/interrupt.h>
  33. #include <net/irda/irda.h>
  34. #include <net/irda/parameters.h>
  35. #include <net/irda/ircomm_core.h>
  36. #include <net/irda/ircomm_tty_attach.h>
  37. #include <net/irda/ircomm_tty.h>
  38. #include <net/irda/ircomm_param.h>
  39. static int ircomm_param_service_type(void *instance, irda_param_t *param,
  40. int get);
  41. static int ircomm_param_port_type(void *instance, irda_param_t *param,
  42. int get);
  43. static int ircomm_param_port_name(void *instance, irda_param_t *param,
  44. int get);
  45. static int ircomm_param_service_type(void *instance, irda_param_t *param,
  46. int get);
  47. static int ircomm_param_data_rate(void *instance, irda_param_t *param,
  48. int get);
  49. static int ircomm_param_data_format(void *instance, irda_param_t *param,
  50. int get);
  51. static int ircomm_param_flow_control(void *instance, irda_param_t *param,
  52. int get);
  53. static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get);
  54. static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get);
  55. static int ircomm_param_line_status(void *instance, irda_param_t *param,
  56. int get);
  57. static int ircomm_param_dte(void *instance, irda_param_t *param, int get);
  58. static int ircomm_param_dce(void *instance, irda_param_t *param, int get);
  59. static int ircomm_param_poll(void *instance, irda_param_t *param, int get);
  60. static pi_minor_info_t pi_minor_call_table_common[] = {
  61. { ircomm_param_service_type, PV_INT_8_BITS },
  62. { ircomm_param_port_type, PV_INT_8_BITS },
  63. { ircomm_param_port_name, PV_STRING }
  64. };
  65. static pi_minor_info_t pi_minor_call_table_non_raw[] = {
  66. { ircomm_param_data_rate, PV_INT_32_BITS | PV_BIG_ENDIAN },
  67. { ircomm_param_data_format, PV_INT_8_BITS },
  68. { ircomm_param_flow_control, PV_INT_8_BITS },
  69. { ircomm_param_xon_xoff, PV_INT_16_BITS },
  70. { ircomm_param_enq_ack, PV_INT_16_BITS },
  71. { ircomm_param_line_status, PV_INT_8_BITS }
  72. };
  73. static pi_minor_info_t pi_minor_call_table_9_wire[] = {
  74. { ircomm_param_dte, PV_INT_8_BITS },
  75. { ircomm_param_dce, PV_INT_8_BITS },
  76. { ircomm_param_poll, PV_NO_VALUE },
  77. };
  78. static pi_major_info_t pi_major_call_table[] = {
  79. { pi_minor_call_table_common, 3 },
  80. { pi_minor_call_table_non_raw, 6 },
  81. { pi_minor_call_table_9_wire, 3 }
  82. /* { pi_minor_call_table_centronics } */
  83. };
  84. pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 };
  85. /*
  86. * Function ircomm_param_request (self, pi, flush)
  87. *
  88. * Queue a parameter for the control channel
  89. *
  90. */
  91. int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
  92. {
  93. unsigned long flags;
  94. struct sk_buff *skb;
  95. int count;
  96. IRDA_DEBUG(2, "%s()\n", __func__ );
  97. IRDA_ASSERT(self != NULL, return -1;);
  98. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  99. /* Make sure we don't send parameters for raw mode */
  100. if (self->service_type == IRCOMM_3_WIRE_RAW)
  101. return 0;
  102. spin_lock_irqsave(&self->spinlock, flags);
  103. skb = self->ctrl_skb;
  104. if (!skb) {
  105. skb = alloc_skb(256, GFP_ATOMIC);
  106. if (!skb) {
  107. spin_unlock_irqrestore(&self->spinlock, flags);
  108. return -ENOMEM;
  109. }
  110. skb_reserve(skb, self->max_header_size);
  111. self->ctrl_skb = skb;
  112. }
  113. /*
  114. * Inserting is a little bit tricky since we don't know how much
  115. * room we will need. But this should hopefully work OK
  116. */
  117. count = irda_param_insert(self, pi, skb_tail_pointer(skb),
  118. skb_tailroom(skb), &ircomm_param_info);
  119. if (count < 0) {
  120. IRDA_WARNING("%s(), no room for parameter!\n", __func__);
  121. spin_unlock_irqrestore(&self->spinlock, flags);
  122. return -1;
  123. }
  124. skb_put(skb, count);
  125. spin_unlock_irqrestore(&self->spinlock, flags);
  126. IRDA_DEBUG(2, "%s(), skb->len=%d\n", __func__ , skb->len);
  127. if (flush) {
  128. /* ircomm_tty_do_softint will take care of the rest */
  129. schedule_work(&self->tqueue);
  130. }
  131. return count;
  132. }
  133. /*
  134. * Function ircomm_param_service_type (self, buf, len)
  135. *
  136. * Handle service type, this function will both be called after the LM-IAS
  137. * query and then the remote device sends its initial parameters
  138. *
  139. */
  140. static int ircomm_param_service_type(void *instance, irda_param_t *param,
  141. int get)
  142. {
  143. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  144. __u8 service_type = (__u8) param->pv.i;
  145. IRDA_ASSERT(self != NULL, return -1;);
  146. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  147. if (get) {
  148. param->pv.i = self->settings.service_type;
  149. return 0;
  150. }
  151. /* Find all common service types */
  152. service_type &= self->service_type;
  153. if (!service_type) {
  154. IRDA_DEBUG(2,
  155. "%s(), No common service type to use!\n", __func__ );
  156. return -1;
  157. }
  158. IRDA_DEBUG(0, "%s(), services in common=%02x\n", __func__ ,
  159. service_type);
  160. /*
  161. * Now choose a preferred service type of those available
  162. */
  163. if (service_type & IRCOMM_CENTRONICS)
  164. self->settings.service_type = IRCOMM_CENTRONICS;
  165. else if (service_type & IRCOMM_9_WIRE)
  166. self->settings.service_type = IRCOMM_9_WIRE;
  167. else if (service_type & IRCOMM_3_WIRE)
  168. self->settings.service_type = IRCOMM_3_WIRE;
  169. else if (service_type & IRCOMM_3_WIRE_RAW)
  170. self->settings.service_type = IRCOMM_3_WIRE_RAW;
  171. IRDA_DEBUG(0, "%s(), resulting service type=0x%02x\n", __func__ ,
  172. self->settings.service_type);
  173. /*
  174. * Now the line is ready for some communication. Check if we are a
  175. * server, and send over some initial parameters.
  176. * Client do it in ircomm_tty_state_setup().
  177. * Note : we may get called from ircomm_tty_getvalue_confirm(),
  178. * therefore before we even have open any socket. And self->client
  179. * is initialised to TRUE only later. So, we check if the link is
  180. * really initialised. - Jean II
  181. */
  182. if ((self->max_header_size != IRCOMM_TTY_HDR_UNINITIALISED) &&
  183. (!self->client) &&
  184. (self->settings.service_type != IRCOMM_3_WIRE_RAW))
  185. {
  186. /* Init connection */
  187. ircomm_tty_send_initial_parameters(self);
  188. ircomm_tty_link_established(self);
  189. }
  190. return 0;
  191. }
  192. /*
  193. * Function ircomm_param_port_type (self, param)
  194. *
  195. * The port type parameter tells if the devices are serial or parallel.
  196. * Since we only advertise serial service, this parameter should only
  197. * be equal to IRCOMM_SERIAL.
  198. */
  199. static int ircomm_param_port_type(void *instance, irda_param_t *param, int get)
  200. {
  201. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  202. IRDA_ASSERT(self != NULL, return -1;);
  203. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  204. if (get)
  205. param->pv.i = IRCOMM_SERIAL;
  206. else {
  207. self->settings.port_type = (__u8) param->pv.i;
  208. IRDA_DEBUG(0, "%s(), port type=%d\n", __func__ ,
  209. self->settings.port_type);
  210. }
  211. return 0;
  212. }
  213. /*
  214. * Function ircomm_param_port_name (self, param)
  215. *
  216. * Exchange port name
  217. *
  218. */
  219. static int ircomm_param_port_name(void *instance, irda_param_t *param, int get)
  220. {
  221. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  222. IRDA_ASSERT(self != NULL, return -1;);
  223. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  224. if (get) {
  225. IRDA_DEBUG(0, "%s(), not imp!\n", __func__ );
  226. } else {
  227. IRDA_DEBUG(0, "%s(), port-name=%s\n", __func__ , param->pv.c);
  228. strncpy(self->settings.port_name, param->pv.c, 32);
  229. }
  230. return 0;
  231. }
  232. /*
  233. * Function ircomm_param_data_rate (self, param)
  234. *
  235. * Exchange data rate to be used in this settings
  236. *
  237. */
  238. static int ircomm_param_data_rate(void *instance, irda_param_t *param, int get)
  239. {
  240. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  241. IRDA_ASSERT(self != NULL, return -1;);
  242. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  243. if (get)
  244. param->pv.i = self->settings.data_rate;
  245. else
  246. self->settings.data_rate = param->pv.i;
  247. IRDA_DEBUG(2, "%s(), data rate = %d\n", __func__ , param->pv.i);
  248. return 0;
  249. }
  250. /*
  251. * Function ircomm_param_data_format (self, param)
  252. *
  253. * Exchange data format to be used in this settings
  254. *
  255. */
  256. static int ircomm_param_data_format(void *instance, irda_param_t *param,
  257. int get)
  258. {
  259. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  260. IRDA_ASSERT(self != NULL, return -1;);
  261. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  262. if (get)
  263. param->pv.i = self->settings.data_format;
  264. else
  265. self->settings.data_format = (__u8) param->pv.i;
  266. return 0;
  267. }
  268. /*
  269. * Function ircomm_param_flow_control (self, param)
  270. *
  271. * Exchange flow control settings to be used in this settings
  272. *
  273. */
  274. static int ircomm_param_flow_control(void *instance, irda_param_t *param,
  275. int get)
  276. {
  277. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  278. IRDA_ASSERT(self != NULL, return -1;);
  279. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  280. if (get)
  281. param->pv.i = self->settings.flow_control;
  282. else
  283. self->settings.flow_control = (__u8) param->pv.i;
  284. IRDA_DEBUG(1, "%s(), flow control = 0x%02x\n", __func__ , (__u8) param->pv.i);
  285. return 0;
  286. }
  287. /*
  288. * Function ircomm_param_xon_xoff (self, param)
  289. *
  290. * Exchange XON/XOFF characters
  291. *
  292. */
  293. static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get)
  294. {
  295. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  296. IRDA_ASSERT(self != NULL, return -1;);
  297. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  298. if (get) {
  299. param->pv.i = self->settings.xonxoff[0];
  300. param->pv.i |= self->settings.xonxoff[1] << 8;
  301. } else {
  302. self->settings.xonxoff[0] = (__u16) param->pv.i & 0xff;
  303. self->settings.xonxoff[1] = (__u16) param->pv.i >> 8;
  304. }
  305. IRDA_DEBUG(0, "%s(), XON/XOFF = 0x%02x,0x%02x\n", __func__ ,
  306. param->pv.i & 0xff, param->pv.i >> 8);
  307. return 0;
  308. }
  309. /*
  310. * Function ircomm_param_enq_ack (self, param)
  311. *
  312. * Exchange ENQ/ACK characters
  313. *
  314. */
  315. static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get)
  316. {
  317. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  318. IRDA_ASSERT(self != NULL, return -1;);
  319. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  320. if (get) {
  321. param->pv.i = self->settings.enqack[0];
  322. param->pv.i |= self->settings.enqack[1] << 8;
  323. } else {
  324. self->settings.enqack[0] = (__u16) param->pv.i & 0xff;
  325. self->settings.enqack[1] = (__u16) param->pv.i >> 8;
  326. }
  327. IRDA_DEBUG(0, "%s(), ENQ/ACK = 0x%02x,0x%02x\n", __func__ ,
  328. param->pv.i & 0xff, param->pv.i >> 8);
  329. return 0;
  330. }
  331. /*
  332. * Function ircomm_param_line_status (self, param)
  333. *
  334. *
  335. *
  336. */
  337. static int ircomm_param_line_status(void *instance, irda_param_t *param,
  338. int get)
  339. {
  340. IRDA_DEBUG(2, "%s(), not impl.\n", __func__ );
  341. return 0;
  342. }
  343. /*
  344. * Function ircomm_param_dte (instance, param)
  345. *
  346. * If we get here, there must be some sort of null-modem connection, and
  347. * we are probably working in server mode as well.
  348. */
  349. static int ircomm_param_dte(void *instance, irda_param_t *param, int get)
  350. {
  351. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  352. __u8 dte;
  353. IRDA_ASSERT(self != NULL, return -1;);
  354. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  355. if (get)
  356. param->pv.i = self->settings.dte;
  357. else {
  358. dte = (__u8) param->pv.i;
  359. self->settings.dce = 0;
  360. if (dte & IRCOMM_DELTA_DTR)
  361. self->settings.dce |= (IRCOMM_DELTA_DSR|
  362. IRCOMM_DELTA_RI |
  363. IRCOMM_DELTA_CD);
  364. if (dte & IRCOMM_DTR)
  365. self->settings.dce |= (IRCOMM_DSR|
  366. IRCOMM_RI |
  367. IRCOMM_CD);
  368. if (dte & IRCOMM_DELTA_RTS)
  369. self->settings.dce |= IRCOMM_DELTA_CTS;
  370. if (dte & IRCOMM_RTS)
  371. self->settings.dce |= IRCOMM_CTS;
  372. /* Take appropriate actions */
  373. ircomm_tty_check_modem_status(self);
  374. /* Null modem cable emulator */
  375. self->settings.null_modem = TRUE;
  376. }
  377. return 0;
  378. }
  379. /*
  380. * Function ircomm_param_dce (instance, param)
  381. *
  382. *
  383. *
  384. */
  385. static int ircomm_param_dce(void *instance, irda_param_t *param, int get)
  386. {
  387. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  388. __u8 dce;
  389. IRDA_DEBUG(1, "%s(), dce = 0x%02x\n", __func__ , (__u8) param->pv.i);
  390. dce = (__u8) param->pv.i;
  391. IRDA_ASSERT(self != NULL, return -1;);
  392. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  393. self->settings.dce = dce;
  394. /* Check if any of the settings have changed */
  395. if (dce & 0x0f) {
  396. if (dce & IRCOMM_DELTA_CTS) {
  397. IRDA_DEBUG(2, "%s(), CTS\n", __func__ );
  398. }
  399. }
  400. ircomm_tty_check_modem_status(self);
  401. return 0;
  402. }
  403. /*
  404. * Function ircomm_param_poll (instance, param)
  405. *
  406. * Called when the peer device is polling for the line settings
  407. *
  408. */
  409. static int ircomm_param_poll(void *instance, irda_param_t *param, int get)
  410. {
  411. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  412. IRDA_ASSERT(self != NULL, return -1;);
  413. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  414. /* Poll parameters are always of length 0 (just a signal) */
  415. if (!get) {
  416. /* Respond with DTE line settings */
  417. ircomm_param_request(self, IRCOMM_DTE, TRUE);
  418. }
  419. return 0;
  420. }