1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/init.h>
33#include <linux/sched.h>
34
35#include <net/irda/irda.h>
36#include <net/irda/irlmp.h>
37#include <net/irda/iriap.h>
38#include <net/irda/irttp.h>
39#include <net/irda/irias_object.h>
40#include <net/irda/parameters.h>
41
42#include <net/irda/ircomm_core.h>
43#include <net/irda/ircomm_param.h>
44#include <net/irda/ircomm_event.h>
45
46#include <net/irda/ircomm_tty.h>
47#include <net/irda/ircomm_tty_attach.h>
48
49static void ircomm_tty_ias_register(struct ircomm_tty_cb *self);
50static void ircomm_tty_discovery_indication(discinfo_t *discovery,
51 DISCOVERY_MODE mode,
52 void *priv);
53static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
54 struct ias_value *value, void *priv);
55static void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self,
56 int timeout);
57static void ircomm_tty_watchdog_timer_expired(void *data);
58
59static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
60 IRCOMM_TTY_EVENT event,
61 struct sk_buff *skb,
62 struct ircomm_tty_info *info);
63static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
64 IRCOMM_TTY_EVENT event,
65 struct sk_buff *skb,
66 struct ircomm_tty_info *info);
67static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
68 IRCOMM_TTY_EVENT event,
69 struct sk_buff *skb,
70 struct ircomm_tty_info *info);
71static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
72 IRCOMM_TTY_EVENT event,
73 struct sk_buff *skb,
74 struct ircomm_tty_info *info);
75static int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
76 IRCOMM_TTY_EVENT event,
77 struct sk_buff *skb,
78 struct ircomm_tty_info *info);
79static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
80 IRCOMM_TTY_EVENT event,
81 struct sk_buff *skb,
82 struct ircomm_tty_info *info);
83
84const char *const ircomm_tty_state[] = {
85 "IRCOMM_TTY_IDLE",
86 "IRCOMM_TTY_SEARCH",
87 "IRCOMM_TTY_QUERY_PARAMETERS",
88 "IRCOMM_TTY_QUERY_LSAP_SEL",
89 "IRCOMM_TTY_SETUP",
90 "IRCOMM_TTY_READY",
91 "*** ERROR *** ",
92};
93
94#ifdef CONFIG_IRDA_DEBUG
95static const char *const ircomm_tty_event[] = {
96 "IRCOMM_TTY_ATTACH_CABLE",
97 "IRCOMM_TTY_DETACH_CABLE",
98 "IRCOMM_TTY_DATA_REQUEST",
99 "IRCOMM_TTY_DATA_INDICATION",
100 "IRCOMM_TTY_DISCOVERY_REQUEST",
101 "IRCOMM_TTY_DISCOVERY_INDICATION",
102 "IRCOMM_TTY_CONNECT_CONFIRM",
103 "IRCOMM_TTY_CONNECT_INDICATION",
104 "IRCOMM_TTY_DISCONNECT_REQUEST",
105 "IRCOMM_TTY_DISCONNECT_INDICATION",
106 "IRCOMM_TTY_WD_TIMER_EXPIRED",
107 "IRCOMM_TTY_GOT_PARAMETERS",
108 "IRCOMM_TTY_GOT_LSAPSEL",
109 "*** ERROR ****",
110};
111#endif
112
113static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
114 struct sk_buff *skb, struct ircomm_tty_info *info) =
115{
116 ircomm_tty_state_idle,
117 ircomm_tty_state_search,
118 ircomm_tty_state_query_parameters,
119 ircomm_tty_state_query_lsap_sel,
120 ircomm_tty_state_setup,
121 ircomm_tty_state_ready,
122};
123
124
125
126
127
128
129
130
131int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
132{
133 IRDA_DEBUG(0, "%s()\n", __func__ );
134
135 IRDA_ASSERT(self != NULL, return -1;);
136 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
137
138
139 if (ircomm_is_connected(self->ircomm)) {
140 IRDA_DEBUG(0, "%s(), already connected!\n", __func__ );
141 return 0;
142 }
143
144
145 self->tty->hw_stopped = 1;
146
147 ircomm_tty_ias_register(self);
148
149 ircomm_tty_do_event(self, IRCOMM_TTY_ATTACH_CABLE, NULL, NULL);
150
151 return 0;
152}
153
154
155
156
157
158
159
160void ircomm_tty_detach_cable(struct ircomm_tty_cb *self)
161{
162 IRDA_DEBUG(0, "%s()\n", __func__ );
163
164 IRDA_ASSERT(self != NULL, return;);
165 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
166
167 del_timer(&self->watchdog_timer);
168
169
170 if (self->ckey) {
171 irlmp_unregister_client(self->ckey);
172 self->ckey = NULL;
173 }
174
175 if (self->skey) {
176 irlmp_unregister_service(self->skey);
177 self->skey = NULL;
178 }
179
180 if (self->iriap) {
181 iriap_close(self->iriap);
182 self->iriap = NULL;
183 }
184
185
186 if (self->obj) {
187 irias_delete_object(self->obj);
188 self->obj = NULL;
189 }
190
191 ircomm_tty_do_event(self, IRCOMM_TTY_DETACH_CABLE, NULL, NULL);
192
193
194 self->daddr = self->saddr = 0;
195 self->dlsap_sel = self->slsap_sel = 0;
196
197 memset(&self->settings, 0, sizeof(struct ircomm_params));
198}
199
200
201
202
203
204
205
206static void ircomm_tty_ias_register(struct ircomm_tty_cb *self)
207{
208 __u8 oct_seq[6];
209 __u16 hints;
210
211 IRDA_DEBUG(0, "%s()\n", __func__ );
212
213 IRDA_ASSERT(self != NULL, return;);
214 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
215
216
217 hints = irlmp_service_to_hint(S_COMM);
218 if (self->service_type & IRCOMM_3_WIRE_RAW)
219 hints |= irlmp_service_to_hint(S_PRINTER);
220
221
222 if (!self->skey)
223 self->skey = irlmp_register_service(hints);
224
225 if (!self->ckey)
226 self->ckey = irlmp_register_client(hints,
227 ircomm_tty_discovery_indication,
228 NULL, (void *) self);
229
230
231 if (self->obj)
232 return;
233
234 if (self->service_type & IRCOMM_3_WIRE_RAW) {
235
236 self->obj = irias_new_object("IrLPT", IAS_IRLPT_ID);
237 irias_add_integer_attrib(self->obj, "IrDA:IrLMP:LsapSel",
238 self->slsap_sel, IAS_KERNEL_ATTR);
239 } else {
240
241 self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID);
242 irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel",
243 self->slsap_sel, IAS_KERNEL_ATTR);
244
245
246 irda_param_pack(oct_seq, "bbbbbb",
247 IRCOMM_SERVICE_TYPE, 1, self->service_type,
248 IRCOMM_PORT_TYPE, 1, IRCOMM_SERIAL);
249
250
251 irias_add_octseq_attrib(self->obj, "Parameters", oct_seq, 6,
252 IAS_KERNEL_ATTR);
253 }
254 irias_insert_object(self->obj);
255}
256
257
258
259
260
261
262
263static void ircomm_tty_ias_unregister(struct ircomm_tty_cb *self)
264{
265
266
267
268
269
270
271
272
273
274
275
276
277 if (self->obj) {
278 irias_delete_object(self->obj);
279 self->obj = NULL;
280 }
281
282#if 0
283
284
285
286
287 if (self->ckey) {
288 irlmp_unregister_client(self->ckey);
289 self->ckey = NULL;
290 }
291#endif
292}
293
294
295
296
297
298
299
300int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self)
301{
302 IRDA_ASSERT(self != NULL, return -1;);
303 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
304
305 if (self->service_type & IRCOMM_3_WIRE_RAW)
306 return 0;
307
308
309
310
311
312 IRDA_DEBUG(2, "%s(), data-rate = %d\n", __func__ ,
313 self->settings.data_rate);
314 if (!self->settings.data_rate)
315 self->settings.data_rate = 9600;
316 IRDA_DEBUG(2, "%s(), data-format = %d\n", __func__ ,
317 self->settings.data_format);
318 if (!self->settings.data_format)
319 self->settings.data_format = IRCOMM_WSIZE_8;
320
321 IRDA_DEBUG(2, "%s(), flow-control = %d\n", __func__ ,
322 self->settings.flow_control);
323
324
325
326 self->settings.dte = IRCOMM_DTR | IRCOMM_RTS;
327
328
329 if (self->client)
330 ircomm_param_request(self, IRCOMM_SERVICE_TYPE, FALSE);
331 ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE);
332 ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
333
334
335 if (self->settings.service_type == IRCOMM_3_WIRE) {
336 ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
337 return 0;
338 }
339
340
341 ircomm_param_request(self, IRCOMM_FLOW_CONTROL, FALSE);
342#if 0
343 ircomm_param_request(self, IRCOMM_XON_XOFF, FALSE);
344 ircomm_param_request(self, IRCOMM_ENQ_ACK, FALSE);
345#endif
346
347 ircomm_param_request(self, IRCOMM_DTE, TRUE);
348
349 return 0;
350}
351
352
353
354
355
356
357
358
359static void ircomm_tty_discovery_indication(discinfo_t *discovery,
360 DISCOVERY_MODE mode,
361 void *priv)
362{
363 struct ircomm_tty_cb *self;
364 struct ircomm_tty_info info;
365
366 IRDA_DEBUG(2, "%s()\n", __func__ );
367
368
369
370
371
372
373
374
375
376
377
378
379 if(mode == DISCOVERY_PASSIVE)
380 return;
381
382 info.daddr = discovery->daddr;
383 info.saddr = discovery->saddr;
384
385 self = priv;
386 ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
387 NULL, &info);
388}
389
390
391
392
393
394
395
396void ircomm_tty_disconnect_indication(void *instance, void *sap,
397 LM_REASON reason,
398 struct sk_buff *skb)
399{
400 struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
401
402 IRDA_DEBUG(2, "%s()\n", __func__ );
403
404 IRDA_ASSERT(self != NULL, return;);
405 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
406
407 if (!self->tty)
408 return;
409
410
411 self->flow = FLOW_STOP;
412
413
414 self->tty->hw_stopped = 1;
415
416 ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL,
417 NULL);
418}
419
420
421
422
423
424
425
426static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
427 struct ias_value *value,
428 void *priv)
429{
430 struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) priv;
431
432 IRDA_DEBUG(2, "%s()\n", __func__ );
433
434 IRDA_ASSERT(self != NULL, return;);
435 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
436
437
438 iriap_close(self->iriap);
439 self->iriap = NULL;
440
441
442 if (result != IAS_SUCCESS) {
443 IRDA_DEBUG(4, "%s(), got NULL value!\n", __func__ );
444 return;
445 }
446
447 switch (value->type) {
448 case IAS_OCT_SEQ:
449 IRDA_DEBUG(2, "%s(), got octet sequence\n", __func__ );
450
451 irda_param_extract_all(self, value->t.oct_seq, value->len,
452 &ircomm_param_info);
453
454 ircomm_tty_do_event(self, IRCOMM_TTY_GOT_PARAMETERS, NULL,
455 NULL);
456 break;
457 case IAS_INTEGER:
458
459 IRDA_DEBUG(2, "%s(), got lsapsel = %d\n", __func__ ,
460 value->t.integer);
461
462 if (value->t.integer == -1) {
463 IRDA_DEBUG(0, "%s(), invalid value!\n", __func__ );
464 } else
465 self->dlsap_sel = value->t.integer;
466
467 ircomm_tty_do_event(self, IRCOMM_TTY_GOT_LSAPSEL, NULL, NULL);
468 break;
469 case IAS_MISSING:
470 IRDA_DEBUG(0, "%s(), got IAS_MISSING\n", __func__ );
471 break;
472 default:
473 IRDA_DEBUG(0, "%s(), got unknown type!\n", __func__ );
474 break;
475 }
476 irias_delete_value(value);
477}
478
479
480
481
482
483
484
485void ircomm_tty_connect_confirm(void *instance, void *sap,
486 struct qos_info *qos,
487 __u32 max_data_size,
488 __u8 max_header_size,
489 struct sk_buff *skb)
490{
491 struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
492
493 IRDA_DEBUG(2, "%s()\n", __func__ );
494
495 IRDA_ASSERT(self != NULL, return;);
496 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
497
498 self->client = TRUE;
499 self->max_data_size = max_data_size;
500 self->max_header_size = max_header_size;
501 self->flow = FLOW_START;
502
503 ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_CONFIRM, NULL, NULL);
504
505
506}
507
508
509
510
511
512
513
514
515void ircomm_tty_connect_indication(void *instance, void *sap,
516 struct qos_info *qos,
517 __u32 max_data_size,
518 __u8 max_header_size,
519 struct sk_buff *skb)
520{
521 struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
522 int clen;
523
524 IRDA_DEBUG(2, "%s()\n", __func__ );
525
526 IRDA_ASSERT(self != NULL, return;);
527 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
528
529 self->client = FALSE;
530 self->max_data_size = max_data_size;
531 self->max_header_size = max_header_size;
532 self->flow = FLOW_START;
533
534 clen = skb->data[0];
535 if (clen)
536 irda_param_extract_all(self, skb->data+1,
537 IRDA_MIN(skb->len, clen),
538 &ircomm_param_info);
539
540 ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL);
541
542
543}
544
545
546
547
548
549
550
551void ircomm_tty_link_established(struct ircomm_tty_cb *self)
552{
553 IRDA_DEBUG(2, "%s()\n", __func__ );
554
555 IRDA_ASSERT(self != NULL, return;);
556 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
557
558 if (!self->tty)
559 return;
560
561 del_timer(&self->watchdog_timer);
562
563
564
565
566
567
568
569 if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) {
570 IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ );
571 return;
572 } else {
573 IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ );
574
575 self->tty->hw_stopped = 0;
576
577
578 wake_up_interruptible(&self->open_wait);
579 }
580
581 schedule_work(&self->tqueue);
582}
583
584
585
586
587
588
589
590
591static void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self,
592 int timeout)
593{
594 IRDA_ASSERT(self != NULL, return;);
595 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
596
597 irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
598 ircomm_tty_watchdog_timer_expired);
599}
600
601
602
603
604
605
606
607static void ircomm_tty_watchdog_timer_expired(void *data)
608{
609 struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data;
610
611 IRDA_DEBUG(2, "%s()\n", __func__ );
612
613 IRDA_ASSERT(self != NULL, return;);
614 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
615
616 ircomm_tty_do_event(self, IRCOMM_TTY_WD_TIMER_EXPIRED, NULL, NULL);
617}
618
619
620
621
622
623
624
625
626int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
627 struct sk_buff *skb, struct ircomm_tty_info *info)
628{
629 IRDA_ASSERT(self != NULL, return -1;);
630 IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
631
632 IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
633 ircomm_tty_state[self->state], ircomm_tty_event[event]);
634
635 return (*state[self->state])(self, event, skb, info);
636}
637
638
639
640
641
642
643
644static inline void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state)
645{
646
647
648
649
650
651
652
653 self->state = state;
654}
655
656
657
658
659
660
661
662static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
663 IRCOMM_TTY_EVENT event,
664 struct sk_buff *skb,
665 struct ircomm_tty_info *info)
666{
667 int ret = 0;
668
669 IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
670 ircomm_tty_state[self->state], ircomm_tty_event[event]);
671 switch (event) {
672 case IRCOMM_TTY_ATTACH_CABLE:
673
674 ircomm_tty_start_watchdog_timer(self, 3*HZ);
675 ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
676
677 irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
678 break;
679 case IRCOMM_TTY_DISCOVERY_INDICATION:
680 self->daddr = info->daddr;
681 self->saddr = info->saddr;
682
683 if (self->iriap) {
684 IRDA_WARNING("%s(), busy with a previous query\n",
685 __func__);
686 return -EBUSY;
687 }
688
689 self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
690 ircomm_tty_getvalue_confirm);
691
692 iriap_getvaluebyclass_request(self->iriap,
693 self->saddr, self->daddr,
694 "IrDA:IrCOMM", "Parameters");
695
696 ircomm_tty_start_watchdog_timer(self, 3*HZ);
697 ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
698 break;
699 case IRCOMM_TTY_CONNECT_INDICATION:
700 del_timer(&self->watchdog_timer);
701
702
703 ircomm_connect_response(self->ircomm, NULL);
704 ircomm_tty_next_state(self, IRCOMM_TTY_READY);
705 break;
706 case IRCOMM_TTY_WD_TIMER_EXPIRED:
707
708 break;
709 case IRCOMM_TTY_DETACH_CABLE:
710 ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
711 break;
712 default:
713 IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
714 ircomm_tty_event[event]);
715 ret = -EINVAL;
716 }
717 return ret;
718}
719
720
721
722
723
724
725
726static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
727 IRCOMM_TTY_EVENT event,
728 struct sk_buff *skb,
729 struct ircomm_tty_info *info)
730{
731 int ret = 0;
732
733 IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
734 ircomm_tty_state[self->state], ircomm_tty_event[event]);
735
736 switch (event) {
737 case IRCOMM_TTY_DISCOVERY_INDICATION:
738 self->daddr = info->daddr;
739 self->saddr = info->saddr;
740
741 if (self->iriap) {
742 IRDA_WARNING("%s(), busy with a previous query\n",
743 __func__);
744 return -EBUSY;
745 }
746
747 self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
748 ircomm_tty_getvalue_confirm);
749
750 if (self->service_type == IRCOMM_3_WIRE_RAW) {
751 iriap_getvaluebyclass_request(self->iriap, self->saddr,
752 self->daddr, "IrLPT",
753 "IrDA:IrLMP:LsapSel");
754 ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL);
755 } else {
756 iriap_getvaluebyclass_request(self->iriap, self->saddr,
757 self->daddr,
758 "IrDA:IrCOMM",
759 "Parameters");
760
761 ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
762 }
763 ircomm_tty_start_watchdog_timer(self, 3*HZ);
764 break;
765 case IRCOMM_TTY_CONNECT_INDICATION:
766 del_timer(&self->watchdog_timer);
767 ircomm_tty_ias_unregister(self);
768
769
770 ircomm_connect_response(self->ircomm, NULL);
771 ircomm_tty_next_state(self, IRCOMM_TTY_READY);
772 break;
773 case IRCOMM_TTY_WD_TIMER_EXPIRED:
774#if 1
775
776#else
777
778 ircomm_tty_start_watchdog_timer(self, 3*HZ);
779 irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
780#endif
781 break;
782 case IRCOMM_TTY_DETACH_CABLE:
783 ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
784 break;
785 default:
786 IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
787 ircomm_tty_event[event]);
788 ret = -EINVAL;
789 }
790 return ret;
791}
792
793
794
795
796
797
798
799static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
800 IRCOMM_TTY_EVENT event,
801 struct sk_buff *skb,
802 struct ircomm_tty_info *info)
803{
804 int ret = 0;
805
806 IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
807 ircomm_tty_state[self->state], ircomm_tty_event[event]);
808
809 switch (event) {
810 case IRCOMM_TTY_GOT_PARAMETERS:
811 if (self->iriap) {
812 IRDA_WARNING("%s(), busy with a previous query\n",
813 __func__);
814 return -EBUSY;
815 }
816
817 self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
818 ircomm_tty_getvalue_confirm);
819
820 iriap_getvaluebyclass_request(self->iriap, self->saddr,
821 self->daddr, "IrDA:IrCOMM",
822 "IrDA:TinyTP:LsapSel");
823
824 ircomm_tty_start_watchdog_timer(self, 3*HZ);
825 ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL);
826 break;
827 case IRCOMM_TTY_WD_TIMER_EXPIRED:
828
829 ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
830 ircomm_tty_start_watchdog_timer(self, 3*HZ);
831 break;
832 case IRCOMM_TTY_CONNECT_INDICATION:
833 del_timer(&self->watchdog_timer);
834 ircomm_tty_ias_unregister(self);
835
836
837 ircomm_connect_response(self->ircomm, NULL);
838 ircomm_tty_next_state(self, IRCOMM_TTY_READY);
839 break;
840 case IRCOMM_TTY_DETACH_CABLE:
841 ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
842 break;
843 default:
844 IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
845 ircomm_tty_event[event]);
846 ret = -EINVAL;
847 }
848 return ret;
849}
850
851
852
853
854
855
856
857static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
858 IRCOMM_TTY_EVENT event,
859 struct sk_buff *skb,
860 struct ircomm_tty_info *info)
861{
862 int ret = 0;
863
864 IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
865 ircomm_tty_state[self->state], ircomm_tty_event[event]);
866
867 switch (event) {
868 case IRCOMM_TTY_GOT_LSAPSEL:
869
870 ret = ircomm_connect_request(self->ircomm, self->dlsap_sel,
871 self->saddr, self->daddr,
872 NULL, self->service_type);
873 ircomm_tty_start_watchdog_timer(self, 3*HZ);
874 ircomm_tty_next_state(self, IRCOMM_TTY_SETUP);
875 break;
876 case IRCOMM_TTY_WD_TIMER_EXPIRED:
877
878 ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
879 ircomm_tty_start_watchdog_timer(self, 3*HZ);
880 break;
881 case IRCOMM_TTY_CONNECT_INDICATION:
882 del_timer(&self->watchdog_timer);
883 ircomm_tty_ias_unregister(self);
884
885
886 ircomm_connect_response(self->ircomm, NULL);
887 ircomm_tty_next_state(self, IRCOMM_TTY_READY);
888 break;
889 case IRCOMM_TTY_DETACH_CABLE:
890 ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
891 break;
892 default:
893 IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
894 ircomm_tty_event[event]);
895 ret = -EINVAL;
896 }
897 return ret;
898}
899
900
901
902
903
904
905
906static int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
907 IRCOMM_TTY_EVENT event,
908 struct sk_buff *skb,
909 struct ircomm_tty_info *info)
910{
911 int ret = 0;
912
913 IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
914 ircomm_tty_state[self->state], ircomm_tty_event[event]);
915
916 switch (event) {
917 case IRCOMM_TTY_CONNECT_CONFIRM:
918 del_timer(&self->watchdog_timer);
919 ircomm_tty_ias_unregister(self);
920
921
922
923
924
925 ircomm_tty_send_initial_parameters(self);
926 ircomm_tty_link_established(self);
927 ircomm_tty_next_state(self, IRCOMM_TTY_READY);
928 break;
929 case IRCOMM_TTY_CONNECT_INDICATION:
930 del_timer(&self->watchdog_timer);
931 ircomm_tty_ias_unregister(self);
932
933
934 ircomm_connect_response(self->ircomm, NULL);
935 ircomm_tty_next_state(self, IRCOMM_TTY_READY);
936 break;
937 case IRCOMM_TTY_WD_TIMER_EXPIRED:
938
939 ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
940 ircomm_tty_start_watchdog_timer(self, 3*HZ);
941 break;
942 case IRCOMM_TTY_DETACH_CABLE:
943
944 ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
945 break;
946 default:
947 IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
948 ircomm_tty_event[event]);
949 ret = -EINVAL;
950 }
951 return ret;
952}
953
954
955
956
957
958
959
960static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
961 IRCOMM_TTY_EVENT event,
962 struct sk_buff *skb,
963 struct ircomm_tty_info *info)
964{
965 int ret = 0;
966
967 switch (event) {
968 case IRCOMM_TTY_DATA_REQUEST:
969 ret = ircomm_data_request(self->ircomm, skb);
970 break;
971 case IRCOMM_TTY_DETACH_CABLE:
972 ircomm_disconnect_request(self->ircomm, NULL);
973 ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
974 break;
975 case IRCOMM_TTY_DISCONNECT_INDICATION:
976 ircomm_tty_ias_register(self);
977 ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
978 ircomm_tty_start_watchdog_timer(self, 3*HZ);
979
980 if (self->flags & ASYNC_CHECK_CD) {
981
982 self->settings.dce = IRCOMM_DELTA_CD;
983 ircomm_tty_check_modem_status(self);
984 } else {
985 IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ );
986 if (self->tty)
987 tty_hangup(self->tty);
988 }
989 break;
990 default:
991 IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
992 ircomm_tty_event[event]);
993 ret = -EINVAL;
994 }
995 return ret;
996}
997
998