~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/irda/ircomm/ircomm_param.c

Version: ~ [ linux-5.6-rc7 ] ~ [ linux-5.5.11 ] ~ [ linux-5.4.27 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.112 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.174 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.217 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.217 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp