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