ircomm_param.c
Upload User: jlfgdled
Upload Date: 2013-04-10
Package Size: 33168k
Code Size: 13k
Development Platform:

Unix_Linux

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