PageRenderTime 34ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/net/irda/ircomm/ircomm_param.c

https://gitlab.com/maddy.kerneldev/my-linuxppc-next
C | 501 lines | 284 code | 84 blank | 133 comment | 62 complexity | c1c9d03bef311352f6716bf4353aa867 MD5 | raw file
  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 const 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 const 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 const 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 const 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_ASSERT(self != NULL, return -1;);
  95. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  96. /* Make sure we don't send parameters for raw mode */
  97. if (self->service_type == IRCOMM_3_WIRE_RAW)
  98. return 0;
  99. spin_lock_irqsave(&self->spinlock, flags);
  100. skb = self->ctrl_skb;
  101. if (!skb) {
  102. skb = alloc_skb(256, GFP_ATOMIC);
  103. if (!skb) {
  104. spin_unlock_irqrestore(&self->spinlock, flags);
  105. return -ENOMEM;
  106. }
  107. skb_reserve(skb, self->max_header_size);
  108. self->ctrl_skb = skb;
  109. }
  110. /*
  111. * Inserting is a little bit tricky since we don't know how much
  112. * room we will need. But this should hopefully work OK
  113. */
  114. count = irda_param_insert(self, pi, skb_tail_pointer(skb),
  115. skb_tailroom(skb), &ircomm_param_info);
  116. if (count < 0) {
  117. net_warn_ratelimited("%s(), no room for parameter!\n",
  118. __func__);
  119. spin_unlock_irqrestore(&self->spinlock, flags);
  120. return -1;
  121. }
  122. skb_put(skb, count);
  123. pr_debug("%s(), skb->len=%d\n", __func__, skb->len);
  124. spin_unlock_irqrestore(&self->spinlock, flags);
  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. pr_debug("%s(), No common service type to use!\n", __func__);
  153. return -1;
  154. }
  155. pr_debug("%s(), services in common=%02x\n", __func__ ,
  156. service_type);
  157. /*
  158. * Now choose a preferred service type of those available
  159. */
  160. if (service_type & IRCOMM_CENTRONICS)
  161. self->settings.service_type = IRCOMM_CENTRONICS;
  162. else if (service_type & IRCOMM_9_WIRE)
  163. self->settings.service_type = IRCOMM_9_WIRE;
  164. else if (service_type & IRCOMM_3_WIRE)
  165. self->settings.service_type = IRCOMM_3_WIRE;
  166. else if (service_type & IRCOMM_3_WIRE_RAW)
  167. self->settings.service_type = IRCOMM_3_WIRE_RAW;
  168. pr_debug("%s(), resulting service type=0x%02x\n", __func__ ,
  169. self->settings.service_type);
  170. /*
  171. * Now the line is ready for some communication. Check if we are a
  172. * server, and send over some initial parameters.
  173. * Client do it in ircomm_tty_state_setup().
  174. * Note : we may get called from ircomm_tty_getvalue_confirm(),
  175. * therefore before we even have open any socket. And self->client
  176. * is initialised to TRUE only later. So, we check if the link is
  177. * really initialised. - Jean II
  178. */
  179. if ((self->max_header_size != IRCOMM_TTY_HDR_UNINITIALISED) &&
  180. (!self->client) &&
  181. (self->settings.service_type != IRCOMM_3_WIRE_RAW))
  182. {
  183. /* Init connection */
  184. ircomm_tty_send_initial_parameters(self);
  185. ircomm_tty_link_established(self);
  186. }
  187. return 0;
  188. }
  189. /*
  190. * Function ircomm_param_port_type (self, param)
  191. *
  192. * The port type parameter tells if the devices are serial or parallel.
  193. * Since we only advertise serial service, this parameter should only
  194. * be equal to IRCOMM_SERIAL.
  195. */
  196. static int ircomm_param_port_type(void *instance, irda_param_t *param, int get)
  197. {
  198. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  199. IRDA_ASSERT(self != NULL, return -1;);
  200. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  201. if (get)
  202. param->pv.i = IRCOMM_SERIAL;
  203. else {
  204. self->settings.port_type = (__u8) param->pv.i;
  205. pr_debug("%s(), port type=%d\n", __func__ ,
  206. self->settings.port_type);
  207. }
  208. return 0;
  209. }
  210. /*
  211. * Function ircomm_param_port_name (self, param)
  212. *
  213. * Exchange port name
  214. *
  215. */
  216. static int ircomm_param_port_name(void *instance, irda_param_t *param, int get)
  217. {
  218. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  219. IRDA_ASSERT(self != NULL, return -1;);
  220. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  221. if (get) {
  222. pr_debug("%s(), not imp!\n", __func__);
  223. } else {
  224. pr_debug("%s(), port-name=%s\n", __func__ , param->pv.c);
  225. strncpy(self->settings.port_name, param->pv.c, 32);
  226. }
  227. return 0;
  228. }
  229. /*
  230. * Function ircomm_param_data_rate (self, param)
  231. *
  232. * Exchange data rate to be used in this settings
  233. *
  234. */
  235. static int ircomm_param_data_rate(void *instance, irda_param_t *param, int get)
  236. {
  237. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  238. IRDA_ASSERT(self != NULL, return -1;);
  239. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  240. if (get)
  241. param->pv.i = self->settings.data_rate;
  242. else
  243. self->settings.data_rate = param->pv.i;
  244. pr_debug("%s(), data rate = %d\n", __func__ , param->pv.i);
  245. return 0;
  246. }
  247. /*
  248. * Function ircomm_param_data_format (self, param)
  249. *
  250. * Exchange data format to be used in this settings
  251. *
  252. */
  253. static int ircomm_param_data_format(void *instance, irda_param_t *param,
  254. int get)
  255. {
  256. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  257. IRDA_ASSERT(self != NULL, return -1;);
  258. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  259. if (get)
  260. param->pv.i = self->settings.data_format;
  261. else
  262. self->settings.data_format = (__u8) param->pv.i;
  263. return 0;
  264. }
  265. /*
  266. * Function ircomm_param_flow_control (self, param)
  267. *
  268. * Exchange flow control settings to be used in this settings
  269. *
  270. */
  271. static int ircomm_param_flow_control(void *instance, irda_param_t *param,
  272. int get)
  273. {
  274. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  275. IRDA_ASSERT(self != NULL, return -1;);
  276. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  277. if (get)
  278. param->pv.i = self->settings.flow_control;
  279. else
  280. self->settings.flow_control = (__u8) param->pv.i;
  281. pr_debug("%s(), flow control = 0x%02x\n", __func__ , (__u8)param->pv.i);
  282. return 0;
  283. }
  284. /*
  285. * Function ircomm_param_xon_xoff (self, param)
  286. *
  287. * Exchange XON/XOFF characters
  288. *
  289. */
  290. static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get)
  291. {
  292. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  293. IRDA_ASSERT(self != NULL, return -1;);
  294. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  295. if (get) {
  296. param->pv.i = self->settings.xonxoff[0];
  297. param->pv.i |= self->settings.xonxoff[1] << 8;
  298. } else {
  299. self->settings.xonxoff[0] = (__u16) param->pv.i & 0xff;
  300. self->settings.xonxoff[1] = (__u16) param->pv.i >> 8;
  301. }
  302. pr_debug("%s(), XON/XOFF = 0x%02x,0x%02x\n", __func__ ,
  303. param->pv.i & 0xff, param->pv.i >> 8);
  304. return 0;
  305. }
  306. /*
  307. * Function ircomm_param_enq_ack (self, param)
  308. *
  309. * Exchange ENQ/ACK characters
  310. *
  311. */
  312. static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get)
  313. {
  314. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  315. IRDA_ASSERT(self != NULL, return -1;);
  316. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  317. if (get) {
  318. param->pv.i = self->settings.enqack[0];
  319. param->pv.i |= self->settings.enqack[1] << 8;
  320. } else {
  321. self->settings.enqack[0] = (__u16) param->pv.i & 0xff;
  322. self->settings.enqack[1] = (__u16) param->pv.i >> 8;
  323. }
  324. pr_debug("%s(), ENQ/ACK = 0x%02x,0x%02x\n", __func__ ,
  325. param->pv.i & 0xff, param->pv.i >> 8);
  326. return 0;
  327. }
  328. /*
  329. * Function ircomm_param_line_status (self, param)
  330. *
  331. *
  332. *
  333. */
  334. static int ircomm_param_line_status(void *instance, irda_param_t *param,
  335. int get)
  336. {
  337. pr_debug("%s(), not impl.\n", __func__);
  338. return 0;
  339. }
  340. /*
  341. * Function ircomm_param_dte (instance, param)
  342. *
  343. * If we get here, there must be some sort of null-modem connection, and
  344. * we are probably working in server mode as well.
  345. */
  346. static int ircomm_param_dte(void *instance, irda_param_t *param, int get)
  347. {
  348. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  349. __u8 dte;
  350. IRDA_ASSERT(self != NULL, return -1;);
  351. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  352. if (get)
  353. param->pv.i = self->settings.dte;
  354. else {
  355. dte = (__u8) param->pv.i;
  356. self->settings.dce = 0;
  357. if (dte & IRCOMM_DELTA_DTR)
  358. self->settings.dce |= (IRCOMM_DELTA_DSR|
  359. IRCOMM_DELTA_RI |
  360. IRCOMM_DELTA_CD);
  361. if (dte & IRCOMM_DTR)
  362. self->settings.dce |= (IRCOMM_DSR|
  363. IRCOMM_RI |
  364. IRCOMM_CD);
  365. if (dte & IRCOMM_DELTA_RTS)
  366. self->settings.dce |= IRCOMM_DELTA_CTS;
  367. if (dte & IRCOMM_RTS)
  368. self->settings.dce |= IRCOMM_CTS;
  369. /* Take appropriate actions */
  370. ircomm_tty_check_modem_status(self);
  371. /* Null modem cable emulator */
  372. self->settings.null_modem = TRUE;
  373. }
  374. return 0;
  375. }
  376. /*
  377. * Function ircomm_param_dce (instance, param)
  378. *
  379. *
  380. *
  381. */
  382. static int ircomm_param_dce(void *instance, irda_param_t *param, int get)
  383. {
  384. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  385. __u8 dce;
  386. pr_debug("%s(), dce = 0x%02x\n", __func__ , (__u8)param->pv.i);
  387. dce = (__u8) param->pv.i;
  388. IRDA_ASSERT(self != NULL, return -1;);
  389. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  390. self->settings.dce = dce;
  391. /* Check if any of the settings have changed */
  392. if (dce & 0x0f) {
  393. if (dce & IRCOMM_DELTA_CTS) {
  394. pr_debug("%s(), CTS\n", __func__);
  395. }
  396. }
  397. ircomm_tty_check_modem_status(self);
  398. return 0;
  399. }
  400. /*
  401. * Function ircomm_param_poll (instance, param)
  402. *
  403. * Called when the peer device is polling for the line settings
  404. *
  405. */
  406. static int ircomm_param_poll(void *instance, irda_param_t *param, int get)
  407. {
  408. struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
  409. IRDA_ASSERT(self != NULL, return -1;);
  410. IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
  411. /* Poll parameters are always of length 0 (just a signal) */
  412. if (!get) {
  413. /* Respond with DTE line settings */
  414. ircomm_param_request(self, IRCOMM_DTE, TRUE);
  415. }
  416. return 0;
  417. }