ircomm_param.c 14 KB

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