2 * Driver for ST5481 USB ISDN modem
5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
13 #include <linux/init.h>
14 #include <linux/gfp.h>
15 #include <linux/usb.h>
16 #include <linux/netdevice.h>
19 static void ph_connect(struct st5481_adapter
*adapter
);
20 static void ph_disconnect(struct st5481_adapter
*adapter
);
22 static struct Fsm l1fsm
;
24 static char *strL1State
[] =
33 static char *strL1Event
[] =
52 "EV_PH_DEACTIVATE_REQ",
56 static inline void D_L1L2(struct st5481_adapter
*adapter
, int pr
, void *arg
)
58 struct hisax_if
*ifc
= (struct hisax_if
*) &adapter
->hisax_d_if
;
60 ifc
->l1l2(ifc
, pr
, arg
);
64 l1_go_f3(struct FsmInst
*fi
, int event
, void *arg
)
66 struct st5481_adapter
*adapter
= fi
->userdata
;
68 if (fi
->state
== ST_L1_F7
)
69 ph_disconnect(adapter
);
71 FsmChangeState(fi
, ST_L1_F3
);
72 D_L1L2(adapter
, PH_DEACTIVATE
| INDICATION
, NULL
);
76 l1_go_f6(struct FsmInst
*fi
, int event
, void *arg
)
78 struct st5481_adapter
*adapter
= fi
->userdata
;
80 if (fi
->state
== ST_L1_F7
)
81 ph_disconnect(adapter
);
83 FsmChangeState(fi
, ST_L1_F6
);
87 l1_go_f7(struct FsmInst
*fi
, int event
, void *arg
)
89 struct st5481_adapter
*adapter
= fi
->userdata
;
91 FsmDelTimer(&adapter
->timer
, 0);
93 FsmChangeState(fi
, ST_L1_F7
);
94 D_L1L2(adapter
, PH_ACTIVATE
| INDICATION
, NULL
);
98 l1_go_f8(struct FsmInst
*fi
, int event
, void *arg
)
100 struct st5481_adapter
*adapter
= fi
->userdata
;
102 if (fi
->state
== ST_L1_F7
)
103 ph_disconnect(adapter
);
105 FsmChangeState(fi
, ST_L1_F8
);
109 l1_timer3(struct FsmInst
*fi
, int event
, void *arg
)
111 struct st5481_adapter
*adapter
= fi
->userdata
;
113 st5481_ph_command(adapter
, ST5481_CMD_DR
);
114 FsmChangeState(fi
, ST_L1_F3
);
115 D_L1L2(adapter
, PH_DEACTIVATE
| INDICATION
, NULL
);
119 l1_ignore(struct FsmInst
*fi
, int event
, void *arg
)
124 l1_activate(struct FsmInst
*fi
, int event
, void *arg
)
126 struct st5481_adapter
*adapter
= fi
->userdata
;
128 st5481_ph_command(adapter
, ST5481_CMD_DR
);
129 st5481_ph_command(adapter
, ST5481_CMD_PUP
);
130 FsmRestartTimer(&adapter
->timer
, TIMER3_VALUE
, EV_TIMER3
, NULL
, 2);
131 st5481_ph_command(adapter
, ST5481_CMD_AR8
);
132 FsmChangeState(fi
, ST_L1_F4
);
135 static struct FsmNode L1FnList
[] __initdata
=
137 {ST_L1_F3
, EV_IND_DP
, l1_ignore
},
138 {ST_L1_F3
, EV_IND_AP
, l1_go_f6
},
139 {ST_L1_F3
, EV_IND_AI8
, l1_go_f7
},
140 {ST_L1_F3
, EV_IND_AI10
, l1_go_f7
},
141 {ST_L1_F3
, EV_PH_ACTIVATE_REQ
, l1_activate
},
143 {ST_L1_F4
, EV_TIMER3
, l1_timer3
},
144 {ST_L1_F4
, EV_IND_DP
, l1_go_f3
},
145 {ST_L1_F4
, EV_IND_AP
, l1_go_f6
},
146 {ST_L1_F4
, EV_IND_AI8
, l1_go_f7
},
147 {ST_L1_F4
, EV_IND_AI10
, l1_go_f7
},
149 {ST_L1_F6
, EV_TIMER3
, l1_timer3
},
150 {ST_L1_F6
, EV_IND_DP
, l1_go_f3
},
151 {ST_L1_F6
, EV_IND_AP
, l1_ignore
},
152 {ST_L1_F6
, EV_IND_AI8
, l1_go_f7
},
153 {ST_L1_F6
, EV_IND_AI10
, l1_go_f7
},
154 {ST_L1_F7
, EV_IND_RSY
, l1_go_f8
},
156 {ST_L1_F7
, EV_IND_DP
, l1_go_f3
},
157 {ST_L1_F7
, EV_IND_AP
, l1_go_f6
},
158 {ST_L1_F7
, EV_IND_AI8
, l1_ignore
},
159 {ST_L1_F7
, EV_IND_AI10
, l1_ignore
},
160 {ST_L1_F7
, EV_IND_RSY
, l1_go_f8
},
162 {ST_L1_F8
, EV_TIMER3
, l1_timer3
},
163 {ST_L1_F8
, EV_IND_DP
, l1_go_f3
},
164 {ST_L1_F8
, EV_IND_AP
, l1_go_f6
},
165 {ST_L1_F8
, EV_IND_AI8
, l1_go_f8
},
166 {ST_L1_F8
, EV_IND_AI10
, l1_go_f8
},
167 {ST_L1_F8
, EV_IND_RSY
, l1_ignore
},
170 static void l1m_debug(struct FsmInst
*fi
, char *fmt
, ...)
176 vsnprintf(buf
, sizeof(buf
), fmt
, args
);
181 /* ======================================================================
186 static struct Fsm dout_fsm
;
188 static char *strDoutState
[] =
192 "ST_DOUT_SHORT_INIT",
193 "ST_DOUT_SHORT_WAIT_DEN",
196 "ST_DOUT_LONG_WAIT_DEN",
199 "ST_DOUT_WAIT_FOR_UNDERRUN",
200 "ST_DOUT_WAIT_FOR_NOT_BUSY",
201 "ST_DOUT_WAIT_FOR_STOP",
202 "ST_DOUT_WAIT_FOR_RESET",
205 static char *strDoutEvent
[] =
207 "EV_DOUT_START_XMIT",
216 static void dout_debug(struct FsmInst
*fi
, char *fmt
, ...)
222 vsnprintf(buf
, sizeof(buf
), fmt
, args
);
227 static void dout_stop_event(void *context
)
229 struct st5481_adapter
*adapter
= context
;
231 FsmEvent(&adapter
->d_out
.fsm
, EV_DOUT_STOPPED
, NULL
);
235 * Start the transfer of a D channel frame.
237 static void usb_d_out(struct st5481_adapter
*adapter
, int buf_nr
)
239 struct st5481_d_out
*d_out
= &adapter
->d_out
;
241 unsigned int num_packets
, packet_offset
;
242 int len
, buf_size
, bytes_sent
;
244 struct usb_iso_packet_descriptor
*desc
;
246 if (d_out
->fsm
.state
!= ST_DOUT_NORMAL
)
249 if (test_and_set_bit(buf_nr
, &d_out
->busy
)) {
250 DBG(2, "ep %d urb %d busy %#lx", EP_D_OUT
, buf_nr
, d_out
->busy
);
253 urb
= d_out
->urb
[buf_nr
];
257 buf_size
= NUM_ISO_PACKETS_D
* SIZE_ISO_PACKETS_D_OUT
;
260 len
= isdnhdlc_encode(&d_out
->hdlc_state
,
261 skb
->data
, skb
->len
, &bytes_sent
,
262 urb
->transfer_buffer
, buf_size
);
263 skb_pull(skb
,bytes_sent
);
265 // Send flags or idle
266 len
= isdnhdlc_encode(&d_out
->hdlc_state
,
267 NULL
, 0, &bytes_sent
,
268 urb
->transfer_buffer
, buf_size
);
271 if (len
< buf_size
) {
272 FsmChangeState(&d_out
->fsm
, ST_DOUT_WAIT_FOR_UNDERRUN
);
274 if (skb
&& !skb
->len
) {
275 d_out
->tx_skb
= NULL
;
276 D_L1L2(adapter
, PH_DATA
| CONFIRM
, NULL
);
277 dev_kfree_skb_any(skb
);
281 urb
->transfer_buffer_length
= len
;
284 while (packet_offset
< len
) {
285 desc
= &urb
->iso_frame_desc
[num_packets
];
286 desc
->offset
= packet_offset
;
287 desc
->length
= SIZE_ISO_PACKETS_D_OUT
;
288 if (len
- packet_offset
< desc
->length
)
289 desc
->length
= len
- packet_offset
;
291 packet_offset
+= desc
->length
;
293 urb
->number_of_packets
= num_packets
;
296 urb
->dev
= adapter
->usb_dev
;
297 // Need to transmit the next buffer 2ms after the DEN_EVENT
298 urb
->transfer_flags
= 0;
299 urb
->start_frame
= usb_get_current_frame_number(adapter
->usb_dev
)+2;
301 DBG_ISO_PACKET(0x20,urb
);
303 if (usb_submit_urb(urb
, GFP_KERNEL
) < 0) {
304 // There is another URB queued up
305 urb
->transfer_flags
= URB_ISO_ASAP
;
306 SUBMIT_URB(urb
, GFP_KERNEL
);
310 static void fifo_reseted(void *context
)
312 struct st5481_adapter
*adapter
= context
;
314 FsmEvent(&adapter
->d_out
.fsm
, EV_DOUT_RESETED
, NULL
);
317 static void usb_d_out_complete(struct urb
*urb
)
319 struct st5481_adapter
*adapter
= urb
->context
;
320 struct st5481_d_out
*d_out
= &adapter
->d_out
;
325 buf_nr
= get_buf_nr(d_out
->urb
, urb
);
326 test_and_clear_bit(buf_nr
, &d_out
->busy
);
328 if (unlikely(urb
->status
< 0)) {
329 switch (urb
->status
) {
333 DBG(1,"urb killed status %d", urb
->status
);
336 WARNING("urb status %d",urb
->status
);
337 if (d_out
->busy
== 0) {
338 st5481_usb_pipe_reset(adapter
, EP_D_OUT
| USB_DIR_OUT
, fifo_reseted
, adapter
);
345 FsmEvent(&adapter
->d_out
.fsm
, EV_DOUT_COMPLETE
, (void *) buf_nr
);
348 /* ====================================================================== */
350 static void dout_start_xmit(struct FsmInst
*fsm
, int event
, void *arg
)
352 struct st5481_adapter
*adapter
= fsm
->userdata
;
353 struct st5481_d_out
*d_out
= &adapter
->d_out
;
361 DBG(2,"len=%d",skb
->len
);
363 isdnhdlc_out_init(&d_out
->hdlc_state
, HDLC_DCHANNEL
| HDLC_BITREVERSE
);
365 if (test_and_set_bit(buf_nr
, &d_out
->busy
)) {
366 WARNING("ep %d urb %d busy %#lx", EP_D_OUT
, buf_nr
, d_out
->busy
);
369 urb
= d_out
->urb
[buf_nr
];
372 len
= isdnhdlc_encode(&d_out
->hdlc_state
,
373 skb
->data
, skb
->len
, &bytes_sent
,
374 urb
->transfer_buffer
, 16);
375 skb_pull(skb
, bytes_sent
);
378 FsmChangeState(&d_out
->fsm
, ST_DOUT_SHORT_INIT
);
380 FsmChangeState(&d_out
->fsm
, ST_DOUT_LONG_INIT
);
383 d_out
->tx_skb
= NULL
;
384 D_L1L2(adapter
, PH_DATA
| CONFIRM
, NULL
);
385 dev_kfree_skb_any(skb
);
389 urb
->transfer_buffer_length
= len
;
391 urb
->iso_frame_desc
[0].offset
= 0;
392 urb
->iso_frame_desc
[0].length
= len
;
393 urb
->number_of_packets
= 1;
396 urb
->dev
= adapter
->usb_dev
;
397 urb
->transfer_flags
= URB_ISO_ASAP
;
399 DBG_ISO_PACKET(0x20,urb
);
400 SUBMIT_URB(urb
, GFP_KERNEL
);
403 static void dout_short_fifo(struct FsmInst
*fsm
, int event
, void *arg
)
405 struct st5481_adapter
*adapter
= fsm
->userdata
;
406 struct st5481_d_out
*d_out
= &adapter
->d_out
;
408 FsmChangeState(&d_out
->fsm
, ST_DOUT_SHORT_WAIT_DEN
);
409 st5481_usb_device_ctrl_msg(adapter
, OUT_D_COUNTER
, 16, NULL
, NULL
);
412 static void dout_end_short_frame(struct FsmInst
*fsm
, int event
, void *arg
)
414 struct st5481_adapter
*adapter
= fsm
->userdata
;
415 struct st5481_d_out
*d_out
= &adapter
->d_out
;
417 FsmChangeState(&d_out
->fsm
, ST_DOUT_WAIT_FOR_UNDERRUN
);
420 static void dout_long_enable_fifo(struct FsmInst
*fsm
, int event
, void *arg
)
422 struct st5481_adapter
*adapter
= fsm
->userdata
;
423 struct st5481_d_out
*d_out
= &adapter
->d_out
;
425 st5481_usb_device_ctrl_msg(adapter
, OUT_D_COUNTER
, 16, NULL
, NULL
);
426 FsmChangeState(&d_out
->fsm
, ST_DOUT_LONG_WAIT_DEN
);
429 static void dout_long_den(struct FsmInst
*fsm
, int event
, void *arg
)
431 struct st5481_adapter
*adapter
= fsm
->userdata
;
432 struct st5481_d_out
*d_out
= &adapter
->d_out
;
434 FsmChangeState(&d_out
->fsm
, ST_DOUT_NORMAL
);
435 usb_d_out(adapter
, 0);
436 usb_d_out(adapter
, 1);
439 static void dout_reset(struct FsmInst
*fsm
, int event
, void *arg
)
441 struct st5481_adapter
*adapter
= fsm
->userdata
;
442 struct st5481_d_out
*d_out
= &adapter
->d_out
;
444 FsmChangeState(&d_out
->fsm
, ST_DOUT_WAIT_FOR_RESET
);
445 st5481_usb_pipe_reset(adapter
, EP_D_OUT
| USB_DIR_OUT
, fifo_reseted
, adapter
);
448 static void dout_stop(struct FsmInst
*fsm
, int event
, void *arg
)
450 struct st5481_adapter
*adapter
= fsm
->userdata
;
451 struct st5481_d_out
*d_out
= &adapter
->d_out
;
453 FsmChangeState(&d_out
->fsm
, ST_DOUT_WAIT_FOR_STOP
);
454 st5481_usb_device_ctrl_msg(adapter
, OUT_D_COUNTER
, 0, dout_stop_event
, adapter
);
457 static void dout_underrun(struct FsmInst
*fsm
, int event
, void *arg
)
459 struct st5481_adapter
*adapter
= fsm
->userdata
;
460 struct st5481_d_out
*d_out
= &adapter
->d_out
;
462 if (test_bit(0, &d_out
->busy
) || test_bit(1, &d_out
->busy
)) {
463 FsmChangeState(&d_out
->fsm
, ST_DOUT_WAIT_FOR_NOT_BUSY
);
465 dout_stop(fsm
, event
, arg
);
469 static void dout_check_busy(struct FsmInst
*fsm
, int event
, void *arg
)
471 struct st5481_adapter
*adapter
= fsm
->userdata
;
472 struct st5481_d_out
*d_out
= &adapter
->d_out
;
474 if (!test_bit(0, &d_out
->busy
) && !test_bit(1, &d_out
->busy
))
475 dout_stop(fsm
, event
, arg
);
478 static void dout_reseted(struct FsmInst
*fsm
, int event
, void *arg
)
480 struct st5481_adapter
*adapter
= fsm
->userdata
;
481 struct st5481_d_out
*d_out
= &adapter
->d_out
;
483 FsmChangeState(&d_out
->fsm
, ST_DOUT_NONE
);
485 FsmEvent(&d_out
->fsm
, EV_DOUT_START_XMIT
, NULL
);
488 static void dout_complete(struct FsmInst
*fsm
, int event
, void *arg
)
490 struct st5481_adapter
*adapter
= fsm
->userdata
;
491 long buf_nr
= (long) arg
;
493 usb_d_out(adapter
, buf_nr
);
496 static void dout_ignore(struct FsmInst
*fsm
, int event
, void *arg
)
500 static struct FsmNode DoutFnList
[] __initdata
=
502 {ST_DOUT_NONE
, EV_DOUT_START_XMIT
, dout_start_xmit
},
504 {ST_DOUT_SHORT_INIT
, EV_DOUT_COMPLETE
, dout_short_fifo
},
506 {ST_DOUT_SHORT_WAIT_DEN
, EV_DOUT_DEN
, dout_end_short_frame
},
507 {ST_DOUT_SHORT_WAIT_DEN
, EV_DOUT_UNDERRUN
, dout_underrun
},
509 {ST_DOUT_LONG_INIT
, EV_DOUT_COMPLETE
, dout_long_enable_fifo
},
511 {ST_DOUT_LONG_WAIT_DEN
, EV_DOUT_DEN
, dout_long_den
},
512 {ST_DOUT_LONG_WAIT_DEN
, EV_DOUT_UNDERRUN
, dout_underrun
},
514 {ST_DOUT_NORMAL
, EV_DOUT_UNDERRUN
, dout_underrun
},
515 {ST_DOUT_NORMAL
, EV_DOUT_COMPLETE
, dout_complete
},
517 {ST_DOUT_WAIT_FOR_UNDERRUN
, EV_DOUT_UNDERRUN
, dout_underrun
},
518 {ST_DOUT_WAIT_FOR_UNDERRUN
, EV_DOUT_COMPLETE
, dout_ignore
},
520 {ST_DOUT_WAIT_FOR_NOT_BUSY
, EV_DOUT_COMPLETE
, dout_check_busy
},
522 {ST_DOUT_WAIT_FOR_STOP
, EV_DOUT_STOPPED
, dout_reset
},
524 {ST_DOUT_WAIT_FOR_RESET
, EV_DOUT_RESETED
, dout_reseted
},
527 void st5481_d_l2l1(struct hisax_if
*hisax_d_if
, int pr
, void *arg
)
529 struct st5481_adapter
*adapter
= hisax_d_if
->priv
;
530 struct sk_buff
*skb
= arg
;
533 case PH_ACTIVATE
| REQUEST
:
534 FsmEvent(&adapter
->l1m
, EV_PH_ACTIVATE_REQ
, NULL
);
536 case PH_DEACTIVATE
| REQUEST
:
537 FsmEvent(&adapter
->l1m
, EV_PH_DEACTIVATE_REQ
, NULL
);
539 case PH_DATA
| REQUEST
:
540 DBG(2, "PH_DATA REQUEST len %d", skb
->len
);
541 BUG_ON(adapter
->d_out
.tx_skb
);
542 adapter
->d_out
.tx_skb
= skb
;
543 FsmEvent(&adapter
->d_out
.fsm
, EV_DOUT_START_XMIT
, NULL
);
546 WARNING("pr %#x\n", pr
);
551 /* ======================================================================
555 * Start receiving on the D channel since entered state F7.
557 static void ph_connect(struct st5481_adapter
*adapter
)
559 struct st5481_d_out
*d_out
= &adapter
->d_out
;
560 struct st5481_in
*d_in
= &adapter
->d_in
;
564 FsmChangeState(&d_out
->fsm
, ST_DOUT_NONE
);
566 // st5481_usb_device_ctrl_msg(adapter, FFMSK_D, OUT_UNDERRUN, NULL, NULL);
567 st5481_usb_device_ctrl_msg(adapter
, FFMSK_D
, 0xfc, NULL
, NULL
);
568 st5481_in_mode(d_in
, L1_MODE_HDLC
);
571 // Turn loopback on (data sent on B and D looped back)
572 st5481_usb_device_ctrl_msg(cs
, LBB
, 0x04, NULL
, NULL
);
575 st5481_usb_pipe_reset(adapter
, EP_D_OUT
| USB_DIR_OUT
, NULL
, NULL
);
577 // Turn on the green LED to tell that we are in state F7
578 adapter
->leds
|= GREEN_LED
;
579 st5481_usb_device_ctrl_msg(adapter
, GPIO_OUT
, adapter
->leds
, NULL
, NULL
);
583 * Stop receiving on the D channel since not in state F7.
585 static void ph_disconnect(struct st5481_adapter
*adapter
)
589 st5481_in_mode(&adapter
->d_in
, L1_MODE_NULL
);
591 // Turn off the green LED to tell that we left state F7
592 adapter
->leds
&= ~GREEN_LED
;
593 st5481_usb_device_ctrl_msg(adapter
, GPIO_OUT
, adapter
->leds
, NULL
, NULL
);
596 static int st5481_setup_d_out(struct st5481_adapter
*adapter
)
598 struct usb_device
*dev
= adapter
->usb_dev
;
599 struct usb_interface
*intf
;
600 struct usb_host_interface
*altsetting
= NULL
;
601 struct usb_host_endpoint
*endpoint
;
602 struct st5481_d_out
*d_out
= &adapter
->d_out
;
606 intf
= usb_ifnum_to_if(dev
, 0);
608 altsetting
= usb_altnum_to_altsetting(intf
, 3);
612 // Allocate URBs and buffers for the D channel out
613 endpoint
= &altsetting
->endpoint
[EP_D_OUT
-1];
615 DBG(2,"endpoint address=%02x,packet size=%d",
616 endpoint
->desc
.bEndpointAddress
, le16_to_cpu(endpoint
->desc
.wMaxPacketSize
));
618 return st5481_setup_isocpipes(d_out
->urb
, dev
,
619 usb_sndisocpipe(dev
, endpoint
->desc
.bEndpointAddress
),
620 NUM_ISO_PACKETS_D
, SIZE_ISO_PACKETS_D_OUT
,
621 NUM_ISO_PACKETS_D
* SIZE_ISO_PACKETS_D_OUT
,
622 usb_d_out_complete
, adapter
);
625 static void st5481_release_d_out(struct st5481_adapter
*adapter
)
627 struct st5481_d_out
*d_out
= &adapter
->d_out
;
631 st5481_release_isocpipes(d_out
->urb
);
634 int st5481_setup_d(struct st5481_adapter
*adapter
)
640 retval
= st5481_setup_d_out(adapter
);
643 adapter
->d_in
.bufsize
= MAX_DFRAME_LEN_L1
;
644 adapter
->d_in
.num_packets
= NUM_ISO_PACKETS_D
;
645 adapter
->d_in
.packet_size
= SIZE_ISO_PACKETS_D_IN
;
646 adapter
->d_in
.ep
= EP_D_IN
| USB_DIR_IN
;
647 adapter
->d_in
.counter
= IN_D_COUNTER
;
648 adapter
->d_in
.adapter
= adapter
;
649 adapter
->d_in
.hisax_if
= &adapter
->hisax_d_if
.ifc
;
650 retval
= st5481_setup_in(&adapter
->d_in
);
654 adapter
->l1m
.fsm
= &l1fsm
;
655 adapter
->l1m
.state
= ST_L1_F3
;
656 adapter
->l1m
.debug
= st5481_debug
& 0x100;
657 adapter
->l1m
.userdata
= adapter
;
658 adapter
->l1m
.printdebug
= l1m_debug
;
659 FsmInitTimer(&adapter
->l1m
, &adapter
->timer
);
661 adapter
->d_out
.fsm
.fsm
= &dout_fsm
;
662 adapter
->d_out
.fsm
.state
= ST_DOUT_NONE
;
663 adapter
->d_out
.fsm
.debug
= st5481_debug
& 0x100;
664 adapter
->d_out
.fsm
.userdata
= adapter
;
665 adapter
->d_out
.fsm
.printdebug
= dout_debug
;
670 st5481_release_d_out(adapter
);
675 void st5481_release_d(struct st5481_adapter
*adapter
)
679 st5481_release_in(&adapter
->d_in
);
680 st5481_release_d_out(adapter
);
683 /* ======================================================================
687 int __init
st5481_d_init(void)
691 l1fsm
.state_count
= L1_STATE_COUNT
;
692 l1fsm
.event_count
= L1_EVENT_COUNT
;
693 l1fsm
.strEvent
= strL1Event
;
694 l1fsm
.strState
= strL1State
;
695 retval
= FsmNew(&l1fsm
, L1FnList
, ARRAY_SIZE(L1FnList
));
699 dout_fsm
.state_count
= DOUT_STATE_COUNT
;
700 dout_fsm
.event_count
= DOUT_EVENT_COUNT
;
701 dout_fsm
.strEvent
= strDoutEvent
;
702 dout_fsm
.strState
= strDoutState
;
703 retval
= FsmNew(&dout_fsm
, DoutFnList
, ARRAY_SIZE(DoutFnList
));
716 void st5481_d_exit(void)