1 Index: linux-2.6.21/drivers/char/Kconfig
2 ===================================================================
3 --- linux-2.6.21.orig/drivers/char/Kconfig 2007-05-06 17:07:33.000000000 -0300
4 +++ linux-2.6.21/drivers/char/Kconfig 2007-05-06 17:10:53.000000000 -0300
6 /sys/devices/platform/telco_clock, with a number of files for
7 controlling the behavior of this hardware.
10 + tristate "GSM TS 07.10 Multiplex driver"
13 + This implements the GSM 07.10 multiplex.
15 +config TS0710_MUX_USB
16 + tristate "Motorola USB support for TS 07.10 Multiplex driver"
17 + depends on TS0710_MUX
19 + This ads support for TS 07.10 over USB, as found in motorola
24 Index: linux-2.6.21/drivers/char/Makefile
25 ===================================================================
26 --- linux-2.6.21.orig/drivers/char/Makefile 2007-05-06 17:07:33.000000000 -0300
27 +++ linux-2.6.21/drivers/char/Makefile 2007-05-06 17:10:21.000000000 -0300
29 obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
30 obj-$(CONFIG_TCG_TPM) += tpm/
32 +obj-$(CONFIG_TS0710_MUX) += ts0710_mux.o ts0710_mux_usb.o
35 # Files generated that shall be removed upon make clean
36 clean-files := consolemap_deftbl.c defkeymap.c
38 Index: linux-2.6.21/drivers/char/ts0710.h
39 ===================================================================
40 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
41 +++ linux-2.6.21/drivers/char/ts0710.h 2007-05-06 17:10:21.000000000 -0300
46 + * Portions derived from rfcomm.c, original header as follows:
48 + * Copyright (C) 2000, 2001 Axis Communications AB
50 + * Author: Mats Friden <mats.friden@axis.com>
52 + * This program is free software; you can redistribute it and/or
53 + * modify it under the terms of the GNU General Public License
54 + * as published by the Free Software Foundation; either version 2
55 + * of the License, or (at your option) any later version.
57 + * This program is distributed in the hope that it will be useful,
58 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
59 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60 + * GNU General Public License for more details.
62 + * You should have received a copy of the GNU General Public License
63 + * along with this program; if not, write to the Free Software
64 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
66 + * Exceptionally, Axis Communications AB grants discretionary and
67 + * conditional permissions for additional use of the text contained
68 + * in the company's release of the AXIS OpenBT Stack under the
69 + * provisions set forth hereunder.
71 + * Provided that, if you use the AXIS OpenBT Stack with other files,
72 + * that do not implement functionality as specified in the Bluetooth
73 + * System specification, to produce an executable, this does not by
74 + * itself cause the resulting executable to be covered by the GNU
75 + * General Public License. Your use of that executable is in no way
76 + * restricted on account of using the AXIS OpenBT Stack code with it.
78 + * This exception does not however invalidate any other reasons why
79 + * the executable file might be covered by the provisions of the GNU
80 + * General Public License.
84 + * Copyright (C) 2002 Motorola
86 + * 07/28/2002 Initial version based on rfcomm.c
87 + * 11/18/2002 Modified
90 +#include <linux/config.h>
91 +#include <linux/module.h>
93 +#include <linux/errno.h>
94 +#include <linux/sched.h>
95 +#include <linux/interrupt.h>
96 +#include <linux/tty.h>
97 +#include <linux/tty_flip.h>
98 +#include <linux/fcntl.h>
99 +#include <linux/string.h>
100 +#include <linux/major.h>
101 +#include <linux/mm.h>
102 +#include <linux/init.h>
103 +#include <linux/devfs_fs_kernel.h>
105 +#include <asm/uaccess.h>
106 +#include <asm/system.h>
107 +#include <asm/bitops.h>
109 +#include <asm/byteorder.h>
110 +#include <asm/types.h>
112 +#define TS0710_MAX_CHN 14
114 +#define SET_PF(ctr) ((ctr) | (1 << 4))
115 +#define CLR_PF(ctr) ((ctr) & 0xef)
116 +#define GET_PF(ctr) (((ctr) >> 4) & 0x1)
118 +#define GET_PN_MSG_FRAME_SIZE(pn) ( ((pn)->frame_sizeh << 8) | ((pn)->frame_sizel))
119 +#define SET_PN_MSG_FRAME_SIZE(pn, size) ({ (pn)->frame_sizel = (size) & 0xff; \
120 + (pn)->frame_sizeh = (size) >> 8; })
122 +#define GET_LONG_LENGTH(a) ( ((a).h_len << 7) | ((a).l_len) )
123 +#define SET_LONG_LENGTH(a, length) ({ (a).ea = 0; \
124 + (a).l_len = length & 0x7F; \
125 + (a).h_len = (length >> 7) & 0xFF; })
127 +#define SHORT_CRC_CHECK 3
128 +#define LONG_CRC_CHECK 4
130 +/* FIXME: Should thsi one be define here? */
131 +#define SHORT_PAYLOAD_SIZE 127
137 +#define TS0710_MAX_HDR_SIZE 5
138 +#define DEF_TS0710_MTU 256
140 +#define TS0710_BASIC_FLAG 0xF9
141 +/* the control field */
150 +/* the type field in a multiplexer command packet */
160 +/* V.24 modem control signals */
167 +#define CTRL_CHAN 0 /* The control channel is defined as DLCI 0 */
168 +#define MCC_CMD 1 /* Multiplexer command cr */
169 +#define MCC_RSP 0 /* Multiplexer response cr */
171 +#ifdef __LITTLE_ENDIAN_BITFIELD
178 +} __attribute__ ((packed)) address_field;
183 +} __attribute__ ((packed)) short_length;
189 +} __attribute__ ((packed)) long_length;
192 + address_field addr;
194 + short_length length;
195 +} __attribute__ ((packed)) short_frame_head;
198 + short_frame_head h;
200 +} __attribute__ ((packed)) short_frame;
203 + address_field addr;
205 + long_length length;
207 +} __attribute__ ((packed)) long_frame_head;
212 +} __attribute__ ((packed)) long_frame;
214 +/* Typedefinitions for structures used for the multiplexer commands */
219 +} __attribute__ ((packed)) mcc_type;
223 + short_length length;
225 +} __attribute__ ((packed)) mcc_short_frame_head;
228 + mcc_short_frame_head h;
230 +} __attribute__ ((packed)) mcc_short_frame;
234 + long_length length;
236 +} __attribute__ ((packed)) mcc_long_frame_head;
239 + mcc_long_frame_head h;
241 +} __attribute__ ((packed)) mcc_long_frame;
252 +} __attribute__ ((packed)) v24_sigs;
260 +} __attribute__ ((packed)) brk_sigs;
263 + short_frame_head s_head;
264 + mcc_short_frame_head mcc_s_head;
265 + address_field dlci;
267 + //brk_sigs break_signals;
269 +} __attribute__ ((packed)) msc_msg;
272 +/* conflict with termios.h */
291 + __u8 parity_type:1;
302 +} __attribute__((packed)) parameter_mask;
309 + __u8 parity_type:2;
321 +} __attribute__((packed)) rpn_values;
324 + short_frame_head s_head;
325 + mcc_short_frame_head mcc_s_head;
326 + address_field dlci;
327 + rpn_values rpn_val;
329 +} __attribute__((packed)) rpn_msg;
335 + short_frame_head s_head;
336 + mcc_short_frame_head mcc_s_head;
337 + address_field dlci;
341 +} __attribute__((packed)) rls_msg;
346 + short_frame_head s_head;
347 + mcc_short_frame_head mcc_s_head;
351 + __u8 credit_flow:4;
357 + __u8 max_nbrof_retrans;
360 +} __attribute__ ((packed)) pn_msg;
364 + short_frame_head s_head;
365 + mcc_short_frame_head mcc_s_head;
366 + mcc_type command_type;
368 +} __attribute__ ((packed)) nsc_msg;
371 +#error Only littel-endianess supported now!
384 +enum ts0710_events {
391 + volatile __u8 state;
392 + volatile __u8 flow_control;
393 + volatile __u8 initiated;
394 + volatile __u8 initiator;
395 + volatile __u16 mtu;
396 + wait_queue_head_t open_wait;
397 + wait_queue_head_t close_wait;
400 +/* user space interfaces */
402 + volatile __u8 initiator;
403 + volatile __u8 c_dlci;
404 + volatile __u16 mtu;
405 + volatile __u8 be_testing;
406 + volatile __u32 test_errs;
407 + wait_queue_head_t test_wait;
409 + dlci_struct dlci[TS0710_MAX_CHN];
411 Index: linux-2.6.21/drivers/char/ts0710_mux.c
412 ===================================================================
413 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
414 +++ linux-2.6.21/drivers/char/ts0710_mux.c 2007-05-06 17:10:21.000000000 -0300
417 + * File: mux_driver.c
419 + * Portions derived from rfcomm.c, original header as follows:
421 + * Copyright (C) 2000, 2001 Axis Communications AB
423 + * Author: Mats Friden <mats.friden@axis.com>
425 + * This program is free software; you can redistribute it and/or
426 + * modify it under the terms of the GNU General Public License
427 + * as published by the Free Software Foundation; either version 2
428 + * of the License, or (at your option) any later version.
430 + * This program is distributed in the hope that it will be useful,
431 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
432 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
433 + * GNU General Public License for more details.
435 + * You should have received a copy of the GNU General Public License
436 + * along with this program; if not, write to the Free Software
437 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
439 + * Exceptionally, Axis Communications AB grants discretionary and
440 + * conditional permissions for additional use of the text contained
441 + * in the company's release of the AXIS OpenBT Stack under the
442 + * provisions set forth hereunder.
444 + * Provided that, if you use the AXIS OpenBT Stack with other files,
445 + * that do not implement functionality as specified in the Bluetooth
446 + * System specification, to produce an executable, this does not by
447 + * itself cause the resulting executable to be covered by the GNU
448 + * General Public License. Your use of that executable is in no way
449 + * restricted on account of using the AXIS OpenBT Stack code with it.
451 + * This exception does not however invalidate any other reasons why
452 + * the executable file might be covered by the provisions of the GNU
453 + * General Public License.
457 + * Copyright (C) 2002-2004 Motorola
458 + * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
460 + * 07/28/2002 Initial version
461 + * 11/18/2002 Second version
462 + * 04/21/2004 Add GPRS PROC
464 +#include <linux/config.h>
465 +#include <linux/module.h>
466 +#include <linux/types.h>
468 +#include <linux/kernel.h>
469 +#include <linux/proc_fs.h>
474 +#include <linux/serial.h>
477 +#include <linux/errno.h>
478 +#include <linux/sched.h>
479 +#include <linux/interrupt.h>
480 +#include <linux/tty.h>
481 +#include <linux/tty_flip.h>
482 +#include <linux/fcntl.h>
483 +#include <linux/string.h>
484 +#include <linux/major.h>
485 +#include <linux/mm.h>
486 +#include <linux/slab.h>
487 +#include <linux/init.h>
488 +#include <linux/devfs_fs_kernel.h>
489 +//#include <syslog.h>
491 +#include <asm/uaccess.h>
492 +#include <asm/system.h>
493 +#include <asm/bitops.h>
496 +//#include <linux/usb.h>
497 +#include "ts0710_mux_usb.h"
501 +#include "ts0710_mux.h"
503 +#define TS0710MUX_GPRS_SESSION_MAX 2
504 +#define TS0710MUX_MAJOR 250
505 +#define TS0710MUX_MINOR_START 0
508 + /*#define TS0710MUX_TIME_OUT 30 *//* 300ms */
509 +#define TS0710MUX_TIME_OUT 250 /* 2500ms, for BP UART hardware flow control AP UART */
511 +#define TS0710MUX_IO_DLCI_FC_ON 0x54F2
512 +#define TS0710MUX_IO_DLCI_FC_OFF 0x54F3
513 +#define TS0710MUX_IO_FC_ON 0x54F4
514 +#define TS0710MUX_IO_FC_OFF 0x54F5
516 +#define TS0710MUX_MAX_BUF_SIZE 2048
518 +#define TS0710MUX_SEND_BUF_OFFSET 10
519 +#define TS0710MUX_SEND_BUF_SIZE (DEF_TS0710_MTU + TS0710MUX_SEND_BUF_OFFSET + 34)
520 +#define TS0710MUX_RECV_BUF_SIZE TS0710MUX_SEND_BUF_SIZE
522 +/*For BP UART problem Begin*/
524 +#define ACK_SPACE 66 /* 6 * 11(ACK frame size) */
526 +#define ACK_SPACE 42 /* 6 * 7(ACK frame size) */
528 +/*For BP UART problem End*/
530 + /*#define TS0710MUX_SERIAL_BUF_SIZE (DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE)*//* For BP UART problem */
531 +#define TS0710MUX_SERIAL_BUF_SIZE (DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE + ACK_SPACE) /* For BP UART problem: ACK_SPACE */
533 +#define TS0710MUX_MAX_TOTAL_FRAME_SIZE (DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE + FLAG_SIZE)
534 +#define TS0710MUX_MAX_CHARS_IN_BUF 65535
535 +#define TS0710MUX_THROTTLE_THRESHOLD DEF_TS0710_MTU
537 +#define TEST_PATTERN_SIZE 250
540 +#define DATATAG 0xAA
542 +#define ACK 0x4F /*For BP UART problem */
544 +/*For BP UART problem Begin*/
546 +#define FIRST_BP_SEQ_OFFSET 1 /*offset from start flag */
547 +#define SECOND_BP_SEQ_OFFSET 2 /*offset from start flag */
548 +#define FIRST_AP_SEQ_OFFSET 3 /*offset from start flag */
549 +#define SECOND_AP_SEQ_OFFSET 4 /*offset from start flag */
550 +#define SLIDE_BP_SEQ_OFFSET 5 /*offset from start flag */
551 +#define SEQ_FIELD_SIZE 5
553 +#define SLIDE_BP_SEQ_OFFSET 1 /*offset from start flag */
554 +#define SEQ_FIELD_SIZE 1
557 +#define ADDRESS_FIELD_OFFSET (1 + SEQ_FIELD_SIZE) /*offset from start flag */
558 +/*For BP UART problem End*/
560 +#ifndef UNUSED_PARAM
561 +#define UNUSED_PARAM(v) (void)(v)
564 +#define TS0710MUX_GPRS1_DLCI 7
565 +#define TS0710MUX_GPRS2_DLCI 8
567 +#define TS0710MUX_GPRS1_RECV_COUNT_IDX 0
568 +#define TS0710MUX_GPRS1_SEND_COUNT_IDX 1
569 +#define TS0710MUX_GPRS2_RECV_COUNT_IDX 2
570 +#define TS0710MUX_GPRS2_SEND_COUNT_IDX 3
571 +#define TS0710MUX_COUNT_MAX_IDX 3
572 +#define TS0710MUX_COUNT_IDX_NUM (TS0710MUX_COUNT_MAX_IDX + 1)
574 +static volatile int mux_data_count[TS0710MUX_COUNT_IDX_NUM] = { 0, 0, 0, 0 };
575 +static volatile int mux_data_count2[TS0710MUX_COUNT_IDX_NUM] = { 0, 0, 0, 0 };
576 +static struct semaphore mux_data_count_mutex[TS0710MUX_COUNT_IDX_NUM];
577 +static volatile __u8 post_recv_count_flag = 0;
580 +struct proc_dir_entry *gprs_proc_file = NULL;
581 +ssize_t file_proc_read(struct file *file, char *buf, size_t size,
583 +ssize_t file_proc_write(struct file *file, const char *buf, size_t count,
585 +struct file_operations file_proc_operations = {
586 + read:file_proc_read,
587 + write:file_proc_write,
594 +static __u8 tty2dlci[NR_MUXS] =
595 + { 1, 2, 3, 4, 5, 6, 7, 8, 6, 7, 8, 9, 10, 11, 12, 13 };
596 +static __u8 iscmdtty[NR_MUXS] =
597 + { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
602 +static dlci_tty dlci2tty[] = { {0, 0}, /* DLCI 0 */
603 +{0, 0}, /* DLCI 1 */
604 +{1, 1}, /* DLCI 2 */
605 +{2, 2}, /* DLCI 3 */
606 +{3, 3}, /* DLCI 4 */
607 +{4, 4}, /* DLCI 5 */
608 +{5, 8}, /* DLCI 6 */
609 +{6, 9}, /* DLCI 7 */
610 +{7, 10}, /* DLCI 8 */
611 +{11, 11}, /* DLCI 9 */
612 +{12, 12}, /* DLCI 10 */
613 +{13, 13}, /* DLCI 11 */
614 +{14, 14}, /* DLCI 12 */
619 + volatile __u8 buf[TS0710MUX_SEND_BUF_SIZE];
620 + volatile __u8 *frame;
621 + unsigned long flags;
622 + volatile __u16 length;
623 + volatile __u8 filled;
624 + volatile __u8 dummy; /* Allignment to 4*n bytes */
627 +/* Bit number in flags of mux_send_struct */
630 +struct mux_recv_packet_tag {
633 + struct mux_recv_packet_tag *next;
635 +typedef struct mux_recv_packet_tag mux_recv_packet;
637 +struct mux_recv_struct_tag {
638 + __u8 data[TS0710MUX_RECV_BUF_SIZE];
641 + mux_recv_packet *mux_packet;
642 + struct mux_recv_struct_tag *next;
644 + volatile __u8 post_unthrottle;
646 +typedef struct mux_recv_struct_tag mux_recv_struct;
648 +#define RECV_RUNNING 0
649 +static unsigned long mux_recv_flags = 0;
651 +static mux_send_struct *mux_send_info[NR_MUXS];
652 +static volatile __u8 mux_send_info_flags[NR_MUXS];
653 +static volatile __u8 mux_send_info_idx = NR_MUXS;
655 +static mux_recv_struct *mux_recv_info[NR_MUXS];
656 +static volatile __u8 mux_recv_info_flags[NR_MUXS];
657 +static mux_recv_struct *mux_recv_queue = NULL;
659 +static struct tty_driver mux_driver;
662 +#define COMM_FOR_MUX_DRIVER usb_for_mux_driver
663 +#define COMM_FOR_MUX_TTY usb_for_mux_tty
664 +#define COMM_MUX_DISPATCHER usb_mux_dispatcher
665 +#define COMM_MUX_SENDER usb_mux_sender
667 +#define COMM_FOR_MUX_DRIVER serial_for_mux_driver
668 +#define COMM_FOR_MUX_TTY serial_for_mux_tty
669 +#define COMM_MUX_DISPATCHER serial_mux_dispatcher
670 +#define COMM_MUX_SENDER serial_mux_sender
672 +extern struct list_head *tq_serial_for_mux;
675 +extern struct tty_driver *COMM_FOR_MUX_DRIVER;
676 +extern struct tty_struct *COMM_FOR_MUX_TTY;
677 +extern void (*COMM_MUX_DISPATCHER) (struct tty_struct * tty);
678 +extern void (*COMM_MUX_SENDER) (void);
680 +static struct work_struct send_tqueue;
681 +static struct work_struct receive_tqueue;
682 +static struct work_struct post_recv_tqueue;
684 +static struct tty_struct *mux_table[NR_MUXS];
685 +static struct termios *mux_termios[NR_MUXS];
686 +static struct termios *mux_termios_locked[NR_MUXS];
687 +static volatile short int mux_tty[NR_MUXS];
691 +#define min(a,b) ( (a)<(b) ? (a):(b) )
694 +static int get_count(__u8 idx);
695 +static int set_count(__u8 idx, int count);
696 +static int add_count(__u8 idx, int count);
698 +static int send_ua(ts0710_con * ts0710, __u8 dlci);
699 +static int send_dm(ts0710_con * ts0710, __u8 dlci);
700 +static int send_sabm(ts0710_con * ts0710, __u8 dlci);
701 +static int send_disc(ts0710_con * ts0710, __u8 dlci);
702 +static void queue_uih(mux_send_struct * send_info, __u16 len,
703 + ts0710_con * ts0710, __u8 dlci);
704 +static int send_pn_msg(ts0710_con * ts0710, __u8 prior, __u32 frame_size,
705 + __u8 credit_flow, __u8 credits, __u8 dlci, __u8 cr);
706 +static int send_nsc_msg(ts0710_con * ts0710, mcc_type cmd, __u8 cr);
707 +static void set_uih_hdr(short_frame * uih_pkt, __u8 dlci, __u32 len, __u8 cr);
709 +static __u32 crc_check(__u8 * data, __u32 length, __u8 check_sum);
710 +static __u8 crc_calc(__u8 * data, __u32 length);
711 +static void create_crctable(__u8 table[]);
713 +static void mux_sched_send(void);
715 +static __u8 crctable[256];
717 +static ts0710_con ts0710_connection;
719 +static rpn_values rpn_val;
722 +static int valid_dlci(__u8 dlci)
724 + if ((dlci < TS0710_MAX_CHN) && (dlci > 0))
732 +#ifdef PRINT_OUTPUT_PRINTK
733 +#define TS0710_DEBUG(fmt, arg...) printk(KERN_INFO "MUX " __FUNCTION__ ": " fmt "\n" , ## arg)
736 +static __u8 strDebug[256];
737 +#define TS0710_DEBUG(fmt, arg...) ({ snprintf(strDebug, sizeof(strDebug), "MUX " __FUNCTION__ ": " fmt "\n" , ## arg); \
738 + /*printk("%s", strDebug)*/ezxlogk("MX", strDebug, strlen(strDebug)); })
739 +#endif /* End #ifdef PRINT_OUTPUT_PRINTK */
742 +#define TS0710_DEBUG(fmt...)
743 +#endif /* End #ifdef TS0710DEBUG */
746 +static unsigned char g_tbuf[TS0710MUX_MAX_BUF_SIZE];
747 +#ifdef PRINT_OUTPUT_PRINTK
748 +#define TS0710_LOG(fmt, arg...) printk(fmt, ## arg)
749 +#define TS0710_PRINTK(fmt, arg...) printk(fmt, ## arg)
752 +static __u8 strLog[256];
753 +#define TS0710_LOG(fmt, arg...) ({ snprintf(strLog, sizeof(strLog), fmt, ## arg); \
754 + /*printk("%s", strLog)*/ezxlogk("MX", strLog, strlen(strLog)); })
755 +#define TS0710_PRINTK(fmt, arg...) ({ printk(fmt, ## arg); \
756 + TS0710_LOG(fmt, ## arg); })
757 +#endif /* End #ifdef PRINT_OUTPUT_PRINTK */
760 +#define TS0710_LOG(fmt...)
761 +#define TS0710_PRINTK(fmt, arg...) printk(fmt, ## arg)
762 +#endif /* End #ifdef TS0710LOG */
765 +static void TS0710_DEBUGHEX(__u8 * buf, int len)
767 + static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE];
777 + for (i = 0; (i < len) && (c < (TS0710MUX_MAX_BUF_SIZE - 3)); i++) {
778 + sprintf(&tbuf[c], "%02x ", buf[i]);
783 +#ifdef PRINT_OUTPUT_PRINTK
784 + TS0710_DEBUG("%s", tbuf);
786 + /*printk("%s\n", tbuf) */ ezxlogk("MX", tbuf, c);
789 +static void TS0710_DEBUGSTR(__u8 * buf, int len)
791 + static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE];
797 + if (len > (TS0710MUX_MAX_BUF_SIZE - 1)) {
798 + len = (TS0710MUX_MAX_BUF_SIZE - 1);
801 + memcpy(tbuf, buf, len);
804 +#ifdef PRINT_OUTPUT_PRINTK
805 + /* 0x00 byte in the string pointed by tbuf may truncate the print result */
806 + TS0710_DEBUG("%s", tbuf);
808 + /*printk("%s\n", tbuf) */ ezxlogk("MX", tbuf, len);
812 +#define TS0710_DEBUGHEX(buf, len)
813 +#define TS0710_DEBUGSTR(buf, len)
814 +#endif /* End #ifdef TS0710DEBUG */
817 +static void TS0710_LOGSTR_FRAME(__u8 send, __u8 * data, int len)
819 + short_frame *short_pkt;
820 + long_frame *long_pkt;
821 + __u8 *uih_data_start;
832 + pos += sprintf(&g_tbuf[pos], "<");
833 + short_pkt = (short_frame *) (data + 1); /*For BP UART problem */
835 + /*For BP UART problem */
836 + /*pos += sprintf(&g_tbuf[pos], ">"); */
837 + pos += sprintf(&g_tbuf[pos], ">%d ", *(data + SLIDE_BP_SEQ_OFFSET)); /*For BP UART problem */
840 + pos += sprintf(&g_tbuf[pos], "%02x %02x %02x %02x ", *(data + FIRST_BP_SEQ_OFFSET), *(data + SECOND_BP_SEQ_OFFSET), *(data + FIRST_AP_SEQ_OFFSET), *(data + SECOND_AP_SEQ_OFFSET)); /*For BP UART problem */
843 + short_pkt = (short_frame *) (data + ADDRESS_FIELD_OFFSET); /*For BP UART problem */
846 + /*For BP UART problem */
847 + /*short_pkt = (short_frame *)(data + 1); */
849 + dlci = short_pkt->h.addr.server_chn << 1 | short_pkt->h.addr.d;
850 + switch (CLR_PF(short_pkt->h.control)) {
852 + pos += sprintf(&g_tbuf[pos], "C SABM %d ::", dlci);
855 + pos += sprintf(&g_tbuf[pos], "C UA %d ::", dlci);
858 + pos += sprintf(&g_tbuf[pos], "C DM %d ::", dlci);
861 + pos += sprintf(&g_tbuf[pos], "C DISC %d ::", dlci);
864 + /*For BP UART problem Begin */
866 + pos += sprintf(&g_tbuf[pos], "C ACK %d ", short_pkt->data[0]);
869 + pos += sprintf(&g_tbuf[pos], "%02x %02x %02x %02x ", short_pkt->data[1], short_pkt->data[2], short_pkt->data[3], short_pkt->data[4]); /*For BP UART problem */
872 + pos += sprintf(&g_tbuf[pos], "::");
874 + /*For BP UART problem End */
878 + pos += sprintf(&g_tbuf[pos], "C MCC %d ::", dlci);
881 + if ((short_pkt->h.length.ea) == 0) {
882 + long_pkt = (long_frame *) short_pkt;
883 + uih_len = GET_LONG_LENGTH(long_pkt->h.length);
884 + uih_data_start = long_pkt->h.data;
886 + uih_len = short_pkt->h.length.len;
887 + uih_data_start = short_pkt->data;
889 + switch (*uih_data_start) {
892 + sprintf(&g_tbuf[pos], "I %d A %d ::", dlci,
898 + sprintf(&g_tbuf[pos], "I %d D %d ::", dlci,
906 + pos += sprintf(&g_tbuf[pos], "N!!! %d ::", dlci);
910 + if (len > (sizeof(g_tbuf) - pos - 1)) {
911 + len = (sizeof(g_tbuf) - pos - 1);
914 + memcpy(&g_tbuf[pos], data, len);
918 +#ifdef PRINT_OUTPUT_PRINTK
919 + /* 0x00 byte in the string pointed by g_tbuf may truncate the print result */
920 + TS0710_LOG("%s\n", g_tbuf);
922 + /*printk("%s\n", g_tbuf) */ ezxlogk("MX", g_tbuf, pos);
926 +#define TS0710_LOGSTR_FRAME(send, data, len)
930 +#define my_for_each_task(p) \
931 + for ((p) = current; ((p) = (p)->next_task) != current; )
933 +static void TS0710_SIG2APLOGD(void)
935 + struct task_struct *p;
936 + static __u8 sig = 0;
942 + read_lock(&tasklist_lock);
943 + my_for_each_task(p) {
944 + if (strncmp(p->comm, "aplogd", 6) == 0) {
946 + if (send_sig(SIGUSR2, p, 1) == 0) {
948 + ("MUX: success to send SIGUSR2 to aplogd!\n");
951 + ("MUX: failure to send SIGUSR2 to aplogd!\n");
956 + read_unlock(&tasklist_lock);
959 + TS0710_PRINTK("MUX: not found aplogd!\n");
963 +#define TS0710_SIG2APLOGD()
966 +static int basic_write(ts0710_con * ts0710, __u8 * buf, int len)
970 + UNUSED_PARAM(ts0710);
972 + buf[0] = TS0710_BASIC_FLAG;
973 + buf[len + 1] = TS0710_BASIC_FLAG;
975 + if ((COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)) {
977 + ("MUX basic_write: (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)\n");
981 + ("MUX basic_write: tapisrv might be down!!! (serial_for_mux_driver == 0) || (serial_for_mux_tty == 0)\n");
982 + TS0710_SIG2APLOGD();
988 + TS0710_LOGSTR_FRAME(1, buf, len + 2);
989 + TS0710_DEBUGHEX(buf, len + 2);
991 + res = COMM_FOR_MUX_DRIVER->write(COMM_FOR_MUX_TTY, buf, len + 2);
993 + if (res != len + 2) {
994 + TS0710_PRINTK("MUX basic_write: Write Error!\n");
1001 +/* Functions for the crc-check and calculation */
1003 +#define CRC_VALID 0xcf
1005 +static __u32 crc_check(__u8 * data, __u32 length, __u8 check_sum)
1009 + while (length--) {
1010 + fcs = crctable[fcs ^ *data++];
1012 + fcs = crctable[fcs ^ check_sum];
1013 + TS0710_DEBUG("fcs : %d\n", fcs);
1014 + if (fcs == (uint) 0xcf) { /*CRC_VALID) */
1015 + TS0710_DEBUG("crc_check: CRC check OK\n");
1018 + TS0710_PRINTK("MUX crc_check: CRC check failed\n");
1023 +/* Calculates the checksum according to the ts0710 specification */
1025 +static __u8 crc_calc(__u8 * data, __u32 length)
1029 + while (length--) {
1030 + fcs = crctable[fcs ^ *data++];
1033 + return 0xff - fcs;
1036 +/* Calulates a reversed CRC table for the FCS check */
1038 +static void create_crctable(__u8 table[])
1043 + __u8 code_word = (__u8) 0xe0;
1044 + __u8 sr = (__u8) 0;
1046 + for (j = 0; j < 256; j++) {
1049 + for (i = 0; i < 8; i++) {
1050 + if ((data & 0x1) ^ (sr & 0x1)) {
1066 +static void ts0710_reset_dlci(__u8 j)
1068 + if (j >= TS0710_MAX_CHN)
1071 + ts0710_connection.dlci[j].state = DISCONNECTED;
1072 + ts0710_connection.dlci[j].flow_control = 0;
1073 + ts0710_connection.dlci[j].mtu = DEF_TS0710_MTU;
1074 + ts0710_connection.dlci[j].initiated = 0;
1075 + ts0710_connection.dlci[j].initiator = 0;
1076 + init_waitqueue_head(&ts0710_connection.dlci[j].open_wait);
1077 + init_waitqueue_head(&ts0710_connection.dlci[j].close_wait);
1080 +static void ts0710_reset_con(void)
1084 + ts0710_connection.initiator = 0;
1085 + ts0710_connection.mtu = DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE;
1086 + ts0710_connection.be_testing = 0;
1087 + ts0710_connection.test_errs = 0;
1088 + init_waitqueue_head(&ts0710_connection.test_wait);
1090 + for (j = 0; j < TS0710_MAX_CHN; j++) {
1091 + ts0710_reset_dlci(j);
1095 +static void ts0710_init(void)
1097 + create_crctable(crctable);
1099 + ts0710_reset_con();
1101 + /* Set the values in the rpn octets */
1103 + rpn_val.bit_rate = 7;
1104 + rpn_val.data_bits = 3;
1105 + rpn_val.stop_bit = 0;
1106 + rpn_val.parity = 0;
1107 + rpn_val.parity_type = 0;
1109 + rpn_val.xon_input = 0;
1110 + rpn_val.xon_output = 0;
1111 + rpn_val.rtr_input = 0;
1112 + rpn_val.rtr_output = 0;
1113 + rpn_val.rtc_input = 0;
1114 + rpn_val.rtc_output = 0;
1116 + rpn_val.xon_u8 = 0x11;
1117 + rpn_val.xoff_u8 = 0x13;
1118 + memset(&rpn_val.pm, 0 , 2); *//* Set the mask to zero */
1121 +static void ts0710_upon_disconnect(void)
1123 + ts0710_con *ts0710 = &ts0710_connection;
1126 + for (j = 0; j < TS0710_MAX_CHN; j++) {
1127 + ts0710->dlci[j].state = DISCONNECTED;
1128 + wake_up_interruptible(&ts0710->dlci[j].open_wait);
1129 + wake_up_interruptible(&ts0710->dlci[j].close_wait);
1131 + ts0710->be_testing = 0;
1132 + wake_up_interruptible(&ts0710->test_wait);
1133 + ts0710_reset_con();
1136 +/* Sending packet functions */
1138 +/* Creates a UA packet and puts it at the beginning of the pkt pointer */
1140 +static int send_ua(ts0710_con * ts0710, __u8 dlci)
1142 + __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
1145 + TS0710_DEBUG("send_ua: Creating UA packet to DLCI %d\n", dlci);
1147 + ua = (short_frame *) (buf + 1);
1148 + ua->h.addr.ea = 1;
1149 + ua->h.addr.cr = ((~(ts0710->initiator)) & 0x1);
1150 + ua->h.addr.d = (dlci) & 0x1;
1151 + ua->h.addr.server_chn = (dlci) >> 0x1;
1152 + ua->h.control = SET_PF(UA);
1153 + ua->h.length.ea = 1;
1154 + ua->h.length.len = 0;
1155 + ua->data[0] = crc_calc((__u8 *) ua, SHORT_CRC_CHECK);
1157 + return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
1160 +/* Creates a DM packet and puts it at the beginning of the pkt pointer */
1162 +static int send_dm(ts0710_con * ts0710, __u8 dlci)
1164 + __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
1167 + TS0710_DEBUG("send_dm: Creating DM packet to DLCI %d\n", dlci);
1169 + dm = (short_frame *) (buf + 1);
1170 + dm->h.addr.ea = 1;
1171 + dm->h.addr.cr = ((~(ts0710->initiator)) & 0x1);
1172 + dm->h.addr.d = dlci & 0x1;
1173 + dm->h.addr.server_chn = dlci >> 0x1;
1174 + dm->h.control = SET_PF(DM);
1175 + dm->h.length.ea = 1;
1176 + dm->h.length.len = 0;
1177 + dm->data[0] = crc_calc((__u8 *) dm, SHORT_CRC_CHECK);
1179 + return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
1182 +static int send_sabm(ts0710_con * ts0710, __u8 dlci)
1184 + __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
1185 + short_frame *sabm;
1187 + TS0710_DEBUG("send_sabm: Creating SABM packet to DLCI %d\n", dlci);
1189 + sabm = (short_frame *) (buf + 1);
1190 + sabm->h.addr.ea = 1;
1191 + sabm->h.addr.cr = ((ts0710->initiator) & 0x1);
1192 + sabm->h.addr.d = dlci & 0x1;
1193 + sabm->h.addr.server_chn = dlci >> 0x1;
1194 + sabm->h.control = SET_PF(SABM);
1195 + sabm->h.length.ea = 1;
1196 + sabm->h.length.len = 0;
1197 + sabm->data[0] = crc_calc((__u8 *) sabm, SHORT_CRC_CHECK);
1199 + return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
1202 +static int send_disc(ts0710_con * ts0710, __u8 dlci)
1204 + __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
1205 + short_frame *disc;
1207 + TS0710_DEBUG("send_disc: Creating DISC packet to DLCI %d\n", dlci);
1209 + disc = (short_frame *) (buf + 1);
1210 + disc->h.addr.ea = 1;
1211 + disc->h.addr.cr = ((ts0710->initiator) & 0x1);
1212 + disc->h.addr.d = dlci & 0x1;
1213 + disc->h.addr.server_chn = dlci >> 0x1;
1214 + disc->h.control = SET_PF(DISC);
1215 + disc->h.length.ea = 1;
1216 + disc->h.length.len = 0;
1217 + disc->data[0] = crc_calc((__u8 *) disc, SHORT_CRC_CHECK);
1219 + return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
1222 +static void queue_uih(mux_send_struct * send_info, __u16 len,
1223 + ts0710_con * ts0710, __u8 dlci)
1228 + ("queue_uih: Creating UIH packet with %d bytes data to DLCI %d\n",
1231 + if (len > SHORT_PAYLOAD_SIZE) {
1232 + long_frame *l_pkt;
1234 + size = sizeof(long_frame) + len + FCS_SIZE;
1235 + l_pkt = (long_frame *) (send_info->frame - sizeof(long_frame));
1236 + set_uih_hdr((void *)l_pkt, dlci, len, ts0710->initiator);
1237 + l_pkt->data[len] = crc_calc((__u8 *) l_pkt, LONG_CRC_CHECK);
1238 + send_info->frame = ((__u8 *) l_pkt) - 1;
1240 + short_frame *s_pkt;
1242 + size = sizeof(short_frame) + len + FCS_SIZE;
1244 + (short_frame *) (send_info->frame - sizeof(short_frame));
1245 + set_uih_hdr((void *)s_pkt, dlci, len, ts0710->initiator);
1246 + s_pkt->data[len] = crc_calc((__u8 *) s_pkt, SHORT_CRC_CHECK);
1247 + send_info->frame = ((__u8 *) s_pkt) - 1;
1249 + send_info->length = size;
1252 +/* Multiplexer command packets functions */
1254 +/* Turns on the ts0710 flow control */
1256 +static int ts0710_fcon_msg(ts0710_con * ts0710, __u8 cr)
1259 + mcc_short_frame *mcc_pkt;
1260 + short_frame *uih_pkt;
1263 + size = sizeof(short_frame) + sizeof(mcc_short_frame) + FCS_SIZE;
1264 + uih_pkt = (short_frame *) (buf + 1);
1265 + set_uih_hdr(uih_pkt, CTRL_CHAN, sizeof(mcc_short_frame),
1266 + ts0710->initiator);
1267 + uih_pkt->data[sizeof(mcc_short_frame)] =
1268 + crc_calc((__u8 *) uih_pkt, SHORT_CRC_CHECK);
1269 + mcc_pkt = (mcc_short_frame *) (uih_pkt->data);
1271 + mcc_pkt->h.type.ea = EA;
1272 + mcc_pkt->h.type.cr = cr;
1273 + mcc_pkt->h.type.type = FCON;
1274 + mcc_pkt->h.length.ea = EA;
1275 + mcc_pkt->h.length.len = 0;
1277 + return basic_write(ts0710, buf, size);
1280 +/* Turns off the ts0710 flow control */
1282 +static int ts0710_fcoff_msg(ts0710_con * ts0710, __u8 cr)
1285 + mcc_short_frame *mcc_pkt;
1286 + short_frame *uih_pkt;
1289 + size = (sizeof(short_frame) + sizeof(mcc_short_frame) + FCS_SIZE);
1290 + uih_pkt = (short_frame *) (buf + 1);
1291 + set_uih_hdr(uih_pkt, CTRL_CHAN, sizeof(mcc_short_frame),
1292 + ts0710->initiator);
1293 + uih_pkt->data[sizeof(mcc_short_frame)] =
1294 + crc_calc((__u8 *) uih_pkt, SHORT_CRC_CHECK);
1295 + mcc_pkt = (mcc_short_frame *) (uih_pkt->data);
1297 + mcc_pkt->h.type.ea = 1;
1298 + mcc_pkt->h.type.cr = cr;
1299 + mcc_pkt->h.type.type = FCOFF;
1300 + mcc_pkt->h.length.ea = 1;
1301 + mcc_pkt->h.length.len = 0;
1303 + return basic_write(ts0710, buf, size);
1307 +static int ts0710_rpn_msg(ts0710_con *ts0710, __u8 cr, __u8 dlci, __u8 req)
1314 + fsize = sizeof(rpn_msg);
1317 + fsize -= sizeof(rpn_values);
1320 + psize = (fsize - sizeof(short_frame) - FCS_SIZE);
1322 + rpn_pkt = (rpn_msg *) buf;
1324 + set_uih_hdr((short_frame *) rpn_pkt, CTRL_CHAN, psize, ts0710->initiator);
1326 + rpn_pkt->fcs = crc_calc((__u8*) rpn_pkt, SHORT_CRC_CHECK);
1328 + rpn_pkt->mcc_s_head.type.ea = EA;
1329 + rpn_pkt->mcc_s_head.type.cr = cr;
1330 + rpn_pkt->mcc_s_head.type.type = RPN;
1331 + rpn_pkt->mcc_s_head.length.ea = EA;
1333 + rpn_pkt->dlci.ea = EA;
1334 + rpn_pkt->dlci.cr = 1;
1335 + rpn_pkt->dlci.d = dlci & 1;
1336 + rpn_pkt->dlci.server_chn = (dlci >> 1);
1339 + rpn_pkt->mcc_s_head.length.len = 1;
1340 + rpn_pkt->rpn_val.bit_rate = rpn_pkt->fcs;
1342 + rpn_pkt->mcc_s_head.length.len = 8;
1343 + memcpy(&(rpn_pkt->rpn_val), &rpn_val, sizeof(rpn_values));
1345 + return basic_write(ts0710, buf, fsize);
1349 +static int ts0710_rls_msg(ts0710_con *ts0710, __u8 cr, __u8 dlci, __u8 err_code)
1356 + fsize = sizeof(rls_msg);
1357 + psize = fsize - sizeof(short_frame) - FCS_SIZE;
1358 + rls_pkt = (rls_msg *) buf;
1360 + set_uih_hdr((short_frame *) rls_pkt, CTRL_CHAN, psize, ts0710->initiator);
1361 + rls_pkt->fcs = crc_calc((__u8*) rls_pkt, SHORT_CRC_CHECK);
1363 + rls_pkt->mcc_s_head.type.ea = EA;
1364 + rls_pkt->mcc_s_head.type.cr = cr;
1365 + rls_pkt->mcc_s_head.type.type = RLS;
1366 + rls_pkt->mcc_s_head.length.ea = EA;
1367 + rls_pkt->mcc_s_head.length.len = 2;
1369 + rls_pkt->dlci.ea = EA;
1370 + rls_pkt->dlci.cr = 1;
1371 + rls_pkt->dlci.d = dlci & 1;
1372 + rls_pkt->dlci.server_chn = dlci >> 1;
1373 + rls_pkt->error = err_code;
1376 + return basic_write(ts0710, buf, fsize);
1380 +/* Sends an PN-messages and sets the not negotiable parameters to their
1381 + default values in ts0710 */
1383 +static int send_pn_msg(ts0710_con * ts0710, __u8 prior, __u32 frame_size,
1384 + __u8 credit_flow, __u8 credits, __u8 dlci, __u8 cr)
1390 + ("send_pn_msg: DLCI 0x%02x, prior:0x%02x, frame_size:%d, credit_flow:%x, credits:%d, cr:%x\n",
1391 + dlci, prior, frame_size, credit_flow, credits, cr);
1393 + size = sizeof(pn_msg);
1394 + pn_pkt = (pn_msg *) (buf + 1);
1396 + set_uih_hdr((void *)pn_pkt, CTRL_CHAN,
1397 + size - (sizeof(short_frame) + FCS_SIZE), ts0710->initiator);
1398 + pn_pkt->fcs = crc_calc((__u8 *) pn_pkt, SHORT_CRC_CHECK);
1400 + pn_pkt->mcc_s_head.type.ea = 1;
1401 + pn_pkt->mcc_s_head.type.cr = cr;
1402 + pn_pkt->mcc_s_head.type.type = PN;
1403 + pn_pkt->mcc_s_head.length.ea = 1;
1404 + pn_pkt->mcc_s_head.length.len = 8;
1408 + pn_pkt->dlci = dlci;
1409 + pn_pkt->frame_type = 0;
1410 + pn_pkt->credit_flow = credit_flow;
1411 + pn_pkt->prior = prior;
1412 + pn_pkt->ack_timer = 0;
1413 + SET_PN_MSG_FRAME_SIZE(pn_pkt, frame_size);
1414 + pn_pkt->credits = credits;
1415 + pn_pkt->max_nbrof_retrans = 0;
1417 + return basic_write(ts0710, buf, size);
1420 +/* Send a Not supported command - command, which needs 3 bytes */
1422 +static int send_nsc_msg(ts0710_con * ts0710, mcc_type cmd, __u8 cr)
1428 + size = sizeof(nsc_msg);
1429 + nsc_pkt = (nsc_msg *) (buf + 1);
1431 + set_uih_hdr((void *)nsc_pkt, CTRL_CHAN,
1432 + sizeof(nsc_msg) - sizeof(short_frame) - FCS_SIZE,
1433 + ts0710->initiator);
1435 + nsc_pkt->fcs = crc_calc((__u8 *) nsc_pkt, SHORT_CRC_CHECK);
1437 + nsc_pkt->mcc_s_head.type.ea = 1;
1438 + nsc_pkt->mcc_s_head.type.cr = cr;
1439 + nsc_pkt->mcc_s_head.type.type = NSC;
1440 + nsc_pkt->mcc_s_head.length.ea = 1;
1441 + nsc_pkt->mcc_s_head.length.len = 1;
1443 + nsc_pkt->command_type.ea = 1;
1444 + nsc_pkt->command_type.cr = cmd.cr;
1445 + nsc_pkt->command_type.type = cmd.type;
1447 + return basic_write(ts0710, buf, size);
1450 +static int ts0710_msc_msg(ts0710_con * ts0710, __u8 value, __u8 cr, __u8 dlci)
1456 + size = sizeof(msc_msg);
1457 + msc_pkt = (msc_msg *) (buf + 1);
1459 + set_uih_hdr((void *)msc_pkt, CTRL_CHAN,
1460 + sizeof(msc_msg) - sizeof(short_frame) - FCS_SIZE,
1461 + ts0710->initiator);
1463 + msc_pkt->fcs = crc_calc((__u8 *) msc_pkt, SHORT_CRC_CHECK);
1465 + msc_pkt->mcc_s_head.type.ea = 1;
1466 + msc_pkt->mcc_s_head.type.cr = cr;
1467 + msc_pkt->mcc_s_head.type.type = MSC;
1468 + msc_pkt->mcc_s_head.length.ea = 1;
1469 + msc_pkt->mcc_s_head.length.len = 2;
1471 + msc_pkt->dlci.ea = 1;
1472 + msc_pkt->dlci.cr = 1;
1473 + msc_pkt->dlci.d = dlci & 1;
1474 + msc_pkt->dlci.server_chn = (dlci >> 1) & 0x1f;
1476 + msc_pkt->v24_sigs = value;
1478 + return basic_write(ts0710, buf, size);
1481 +static int ts0710_test_msg(ts0710_con * ts0710, __u8 * test_pattern, __u32 len,
1482 + __u8 cr, __u8 * f_buf /*Frame buf */ )
1486 + if (len > SHORT_PAYLOAD_SIZE) {
1487 + long_frame *uih_pkt;
1488 + mcc_long_frame *mcc_pkt;
1491 + (sizeof(long_frame) + sizeof(mcc_long_frame) + len +
1493 + uih_pkt = (long_frame *) (f_buf + 1);
1495 + set_uih_hdr((short_frame *) uih_pkt, CTRL_CHAN, len +
1496 + sizeof(mcc_long_frame), ts0710->initiator);
1497 + uih_pkt->data[GET_LONG_LENGTH(uih_pkt->h.length)] =
1498 + crc_calc((__u8 *) uih_pkt, LONG_CRC_CHECK);
1499 + mcc_pkt = (mcc_long_frame *) uih_pkt->data;
1501 + mcc_pkt->h.type.ea = EA;
1502 + /* cr tells whether it is a commmand (1) or a response (0) */
1503 + mcc_pkt->h.type.cr = cr;
1504 + mcc_pkt->h.type.type = TEST;
1505 + SET_LONG_LENGTH(mcc_pkt->h.length, len);
1506 + memcpy(mcc_pkt->value, test_pattern, len);
1507 + } else if (len > (SHORT_PAYLOAD_SIZE - sizeof(mcc_short_frame))) {
1508 + long_frame *uih_pkt;
1509 + mcc_short_frame *mcc_pkt;
1511 + /* Create long uih packet and short mcc packet */
1513 + (sizeof(long_frame) + sizeof(mcc_short_frame) + len +
1515 + uih_pkt = (long_frame *) (f_buf + 1);
1517 + set_uih_hdr((short_frame *) uih_pkt, CTRL_CHAN,
1518 + len + sizeof(mcc_short_frame), ts0710->initiator);
1519 + uih_pkt->data[GET_LONG_LENGTH(uih_pkt->h.length)] =
1520 + crc_calc((__u8 *) uih_pkt, LONG_CRC_CHECK);
1521 + mcc_pkt = (mcc_short_frame *) uih_pkt->data;
1523 + mcc_pkt->h.type.ea = EA;
1524 + mcc_pkt->h.type.cr = cr;
1525 + mcc_pkt->h.type.type = TEST;
1526 + mcc_pkt->h.length.ea = EA;
1527 + mcc_pkt->h.length.len = len;
1528 + memcpy(mcc_pkt->value, test_pattern, len);
1530 + short_frame *uih_pkt;
1531 + mcc_short_frame *mcc_pkt;
1534 + (sizeof(short_frame) + sizeof(mcc_short_frame) + len +
1536 + uih_pkt = (short_frame *) (f_buf + 1);
1538 + set_uih_hdr((void *)uih_pkt, CTRL_CHAN, len
1539 + + sizeof(mcc_short_frame), ts0710->initiator);
1540 + uih_pkt->data[uih_pkt->h.length.len] =
1541 + crc_calc((__u8 *) uih_pkt, SHORT_CRC_CHECK);
1542 + mcc_pkt = (mcc_short_frame *) uih_pkt->data;
1544 + mcc_pkt->h.type.ea = EA;
1545 + mcc_pkt->h.type.cr = cr;
1546 + mcc_pkt->h.type.type = TEST;
1547 + mcc_pkt->h.length.ea = EA;
1548 + mcc_pkt->h.length.len = len;
1549 + memcpy(mcc_pkt->value, test_pattern, len);
1552 + return basic_write(ts0710, f_buf, size);
1555 +static void set_uih_hdr(short_frame * uih_pkt, __u8 dlci, __u32 len, __u8 cr)
1557 + uih_pkt->h.addr.ea = 1;
1558 + uih_pkt->h.addr.cr = cr;
1559 + uih_pkt->h.addr.d = dlci & 0x1;
1560 + uih_pkt->h.addr.server_chn = dlci >> 1;
1561 + uih_pkt->h.control = CLR_PF(UIH);
1563 + if (len > SHORT_PAYLOAD_SIZE) {
1564 + SET_LONG_LENGTH(((long_frame *) uih_pkt)->h.length, len);
1566 + uih_pkt->h.length.ea = 1;
1567 + uih_pkt->h.length.len = len;
1571 +/* Parses a multiplexer control channel packet */
1573 +void process_mcc(__u8 * data, __u32 len, ts0710_con * ts0710, int longpkt)
1575 + __u8 *tbuf = NULL;
1576 + mcc_short_frame *mcc_short_pkt;
1581 + (mcc_short_frame *) (((long_frame *) data)->data);
1584 + (mcc_short_frame *) (((short_frame *) data)->data);
1587 + switch (mcc_short_pkt->h.type.type) {
1589 + if (mcc_short_pkt->h.type.cr == MCC_RSP) {
1590 + TS0710_DEBUG("Received test command response\n");
1592 + if (ts0710->be_testing) {
1593 + if ((mcc_short_pkt->h.length.ea) == 0) {
1594 + mcc_long_frame *mcc_long_pkt;
1596 + (mcc_long_frame *) mcc_short_pkt;
1597 + if (GET_LONG_LENGTH
1598 + (mcc_long_pkt->h.length) !=
1599 + TEST_PATTERN_SIZE) {
1600 + ts0710->test_errs =
1601 + TEST_PATTERN_SIZE;
1603 + ("Err: received test pattern is %d bytes long, not expected %d\n",
1605 + (mcc_long_pkt->h.length),
1606 + TEST_PATTERN_SIZE);
1608 + ts0710->test_errs = 0;
1610 + j < TEST_PATTERN_SIZE;
1612 + if (mcc_long_pkt->
1623 +#if TEST_PATTERN_SIZE < 128
1624 + if (mcc_short_pkt->h.length.len !=
1625 + TEST_PATTERN_SIZE) {
1628 + ts0710->test_errs =
1629 + TEST_PATTERN_SIZE;
1631 + ("Err: received test pattern is %d bytes long, not expected %d\n",
1632 + mcc_short_pkt->h.length.
1633 + len, TEST_PATTERN_SIZE);
1635 +#if TEST_PATTERN_SIZE < 128
1637 + ts0710->test_errs = 0;
1639 + j < TEST_PATTERN_SIZE;
1641 + if (mcc_short_pkt->
1653 + ts0710->be_testing = 0; /* Clear the flag */
1654 + wake_up_interruptible(&ts0710->test_wait);
1657 + ("Err: shouldn't or late to get test cmd response\n");
1660 + tbuf = (__u8 *) kmalloc(len + 32, GFP_ATOMIC);
1665 + if ((mcc_short_pkt->h.length.ea) == 0) {
1666 + mcc_long_frame *mcc_long_pkt;
1667 + mcc_long_pkt = (mcc_long_frame *) mcc_short_pkt;
1668 + ts0710_test_msg(ts0710, mcc_long_pkt->value,
1669 + GET_LONG_LENGTH(mcc_long_pkt->h.
1673 + ts0710_test_msg(ts0710, mcc_short_pkt->value,
1674 + mcc_short_pkt->h.length.len,
1682 + case FCON: /*Flow control on command */
1684 + ("MUX Received Flow control(all channels) on command\n");
1685 + if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1686 + ts0710->dlci[0].state = CONNECTED;
1687 + ts0710_fcon_msg(ts0710, MCC_RSP);
1692 + case FCOFF: /*Flow control off command */
1694 + ("MUX Received Flow control(all channels) off command\n");
1695 + if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1696 + for (j = 0; j < TS0710_MAX_CHN; j++) {
1697 + ts0710->dlci[j].state = FLOW_STOPPED;
1699 + ts0710_fcoff_msg(ts0710, MCC_RSP);
1703 + case MSC: /*Modem status command */
1708 + dlci = (mcc_short_pkt->value[0]) >> 2;
1709 + v24_sigs = mcc_short_pkt->value[1];
1711 + if ((ts0710->dlci[dlci].state != CONNECTED)
1712 + && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
1713 + send_dm(ts0710, dlci);
1716 + if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1717 + TS0710_DEBUG("Received Modem status command\n");
1718 + if (v24_sigs & 2) {
1719 + if (ts0710->dlci[dlci].state ==
1722 + ("MUX Received Flow off on dlci %d\n",
1724 + ts0710->dlci[dlci].state =
1728 + if (ts0710->dlci[dlci].state ==
1730 + ts0710->dlci[dlci].state =
1733 + ("MUX Received Flow on on dlci %d\n",
1739 + ts0710_msc_msg(ts0710, v24_sigs, MCC_RSP, dlci);
1741 + if (!(ts0710->dlci[dlci].initiated) && !(ts0710->dlci[dlci].initiator)) {
1742 + ts0710_msc_msg(ts0710, EA | RTR | RTC | DV, MCC_CMD, dlci);
1743 + ts0710->dlci[dlci].initiated = 1;
1748 + ("Received Modem status response\n");
1750 + if (v24_sigs & 2) {
1751 + TS0710_DEBUG("Flow stop accepted\n");
1757 + /* case RPN: *//*Remote port negotiation command */
1762 + dlci = (mcc_short_pkt->value[0]) >> 2;
1764 + if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1765 + if (mcc_short_pkt->h.length.len == 1) {
1766 + TS0710_DEBUG("Received Remote port negotiation command\n");
1767 + ts0710_rpn_msg(ts0710, MCC_RSP, dlci, 0);
1770 + /* Accept the other sides settings (accept all for now) */
1771 +/* TS0710_DEBUG("Received Remote port negotiation respons\n");
1772 + memcpy(&rpn_val, &mcc_short_pkt->value[1], 8);
1773 + ts0710_rpn_msg(ts0710, MCC_RSP, dlci, 0);
1775 + /* Zero the parametermask after response */
1776 +/* memset(&rpn_val.pm, 0, 2);
1783 + case RLS: *//*Remote line status */
1788 + TS0710_DEBUG("Received Remote line status\n");
1789 + if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1790 + dlci = mcc_short_pkt->value[0] >> 2;
1791 + err_code = mcc_short_pkt->value[1];
1793 + ts0710_rls_msg(ts0710, MCC_RSP, dlci, err_code);
1798 + case PN: /*DLC parameter negotiation */
1804 + pn_pkt = (pn_msg *) data;
1805 + dlci = pn_pkt->dlci;
1806 + frame_size = GET_PN_MSG_FRAME_SIZE(pn_pkt);
1808 + ("Received DLC parameter negotiation, PN\n");
1809 + if (pn_pkt->mcc_s_head.type.cr == MCC_CMD) {
1810 + TS0710_DEBUG("received PN command with:\n");
1811 + TS0710_DEBUG("Frame size:%d\n", frame_size);
1814 + min(frame_size, ts0710->dlci[dlci].mtu);
1815 + send_pn_msg(ts0710, pn_pkt->prior, frame_size,
1816 + 0, 0, dlci, MCC_RSP);
1817 + ts0710->dlci[dlci].mtu = frame_size;
1818 + TS0710_DEBUG("process_mcc : mtu set to %d\n",
1819 + ts0710->dlci[dlci].mtu);
1821 + TS0710_DEBUG("received PN response with:\n");
1822 + TS0710_DEBUG("Frame size:%d\n", frame_size);
1825 + min(frame_size, ts0710->dlci[dlci].mtu);
1826 + ts0710->dlci[dlci].mtu = frame_size;
1829 + ("process_mcc : mtu set on dlci:%d to %d\n",
1830 + dlci, ts0710->dlci[dlci].mtu);
1832 + if (ts0710->dlci[dlci].state == NEGOTIATING) {
1833 + ts0710->dlci[dlci].state = CONNECTING;
1834 + wake_up_interruptible(&ts0710->
1842 + case NSC: /*Non supported command resonse */
1843 + TS0710_LOG("MUX Received Non supported command response\n");
1846 + default: /*Non supported command received */
1847 + TS0710_LOG("MUX Received a non supported command\n");
1848 + send_nsc_msg(ts0710, mcc_short_pkt->h.type, MCC_RSP);
1853 +static mux_recv_packet *get_mux_recv_packet(__u32 size)
1855 + mux_recv_packet *recv_packet;
1857 + TS0710_DEBUG("Enter into get_mux_recv_packet");
1860 + (mux_recv_packet *) kmalloc(sizeof(mux_recv_packet), GFP_ATOMIC);
1861 + if (!recv_packet) {
1865 + recv_packet->data = (__u8 *) kmalloc(size, GFP_ATOMIC);
1866 + if (!(recv_packet->data)) {
1867 + kfree(recv_packet);
1870 + recv_packet->length = 0;
1871 + recv_packet->next = 0;
1872 + return recv_packet;
1875 +static void free_mux_recv_packet(mux_recv_packet * recv_packet)
1877 + TS0710_DEBUG("Enter into free_mux_recv_packet");
1879 + if (!recv_packet) {
1883 + if (recv_packet->data) {
1884 + kfree(recv_packet->data);
1886 + kfree(recv_packet);
1889 +static void free_mux_recv_struct(mux_recv_struct * recv_info)
1891 + mux_recv_packet *recv_packet1, *recv_packet2;
1897 + recv_packet1 = recv_info->mux_packet;
1898 + while (recv_packet1) {
1899 + recv_packet2 = recv_packet1->next;
1900 + free_mux_recv_packet(recv_packet1);
1901 + recv_packet1 = recv_packet2;
1907 +static inline void add_post_recv_queue(mux_recv_struct ** head,
1908 + mux_recv_struct * new_item)
1910 + new_item->next = *head;
1914 +static void ts0710_flow_on(__u8 dlci, ts0710_con * ts0710)
1919 + struct tty_struct *tty;
1920 + mux_recv_struct *recv_info;
1922 + if ((ts0710->dlci[0].state != CONNECTED)
1923 + && (ts0710->dlci[0].state != FLOW_STOPPED)) {
1925 + } else if ((ts0710->dlci[dlci].state != CONNECTED)
1926 + && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
1930 + if (!(ts0710->dlci[dlci].flow_control)) {
1934 + cmdtty = dlci2tty[dlci].cmdtty;
1935 + datatty = dlci2tty[dlci].datatty;
1937 + if (cmdtty != datatty) {
1938 + /* Check AT cmd tty */
1939 + tty = mux_table[cmdtty];
1940 + if (mux_tty[cmdtty] && tty) {
1941 + if (test_bit(TTY_THROTTLED, &tty->flags)) {
1945 + recv_info = mux_recv_info[cmdtty];
1946 + if (mux_recv_info_flags[cmdtty] && recv_info) {
1947 + if (recv_info->total) {
1952 + /* Check data tty */
1953 + tty = mux_table[datatty];
1954 + if (mux_tty[datatty] && tty) {
1955 + if (test_bit(TTY_THROTTLED, &tty->flags)) {
1959 + recv_info = mux_recv_info[datatty];
1960 + if (mux_recv_info_flags[datatty] && recv_info) {
1961 + if (recv_info->total) {
1967 + for (i = 0; i < 3; i++) {
1968 + if (ts0710_msc_msg(ts0710, EA | RTC | RTR | DV, MCC_CMD, dlci) <
1972 + TS0710_LOG("MUX send Flow on on dlci %d\n", dlci);
1973 + ts0710->dlci[dlci].flow_control = 0;
1979 +static void ts0710_flow_off(struct tty_struct *tty, __u8 dlci,
1980 + ts0710_con * ts0710)
1984 + if (test_and_set_bit(TTY_THROTTLED, &tty->flags)) {
1988 + if ((ts0710->dlci[0].state != CONNECTED)
1989 + && (ts0710->dlci[0].state != FLOW_STOPPED)) {
1991 + } else if ((ts0710->dlci[dlci].state != CONNECTED)
1992 + && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
1996 + if (ts0710->dlci[dlci].flow_control) {
2000 + for (i = 0; i < 3; i++) {
2001 + if (ts0710_msc_msg
2002 + (ts0710, EA | FC | RTC | RTR | DV, MCC_CMD, dlci) < 0) {
2005 + TS0710_LOG("MUX send Flow off on dlci %d\n", dlci);
2006 + ts0710->dlci[dlci].flow_control = 1;
2012 +int ts0710_recv_data(ts0710_con * ts0710, char *data, int len)
2014 + short_frame *short_pkt;
2015 + long_frame *long_pkt;
2016 + __u8 *uih_data_start;
2019 + __u8 be_connecting;
2024 + short_pkt = (short_frame *) data;
2026 + dlci = short_pkt->h.addr.server_chn << 1 | short_pkt->h.addr.d;
2027 + switch (CLR_PF(short_pkt->h.control)) {
2029 + TS0710_DEBUG("SABM-packet received\n");
2031 +/*For BP UART problem
2032 + if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
2037 + TS0710_DEBUG("server channel == 0\n");
2038 + ts0710->dlci[0].state = CONNECTED;
2040 + TS0710_DEBUG("sending back UA - control channel\n");
2041 + send_ua(ts0710, dlci);
2042 + wake_up_interruptible(&ts0710->dlci[0].open_wait);
2044 + } else if (valid_dlci(dlci)) {
2046 + TS0710_DEBUG("Incomming connect on channel %d\n", dlci);
2048 + TS0710_DEBUG("sending UA, dlci %d\n", dlci);
2049 + send_ua(ts0710, dlci);
2051 + ts0710->dlci[dlci].state = CONNECTED;
2052 + wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
2055 + TS0710_DEBUG("invalid dlci %d, sending DM\n", dlci);
2056 + send_dm(ts0710, dlci);
2062 + TS0710_DEBUG("UA packet received\n");
2064 +/*For BP UART problem
2065 + if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
2070 + TS0710_DEBUG("server channel == 0\n");
2072 + if (ts0710->dlci[0].state == CONNECTING) {
2073 + ts0710->dlci[0].state = CONNECTED;
2074 + wake_up_interruptible(&ts0710->dlci[0].
2076 + } else if (ts0710->dlci[0].state == DISCONNECTING) {
2077 + ts0710_upon_disconnect();
2080 + (" Something wrong receiving UA packet\n");
2082 + } else if (valid_dlci(dlci)) {
2083 + TS0710_DEBUG("Incomming UA on channel %d\n", dlci);
2085 + if (ts0710->dlci[dlci].state == CONNECTING) {
2086 + ts0710->dlci[dlci].state = CONNECTED;
2087 + wake_up_interruptible(&ts0710->dlci[dlci].
2089 + } else if (ts0710->dlci[dlci].state == DISCONNECTING) {
2090 + ts0710->dlci[dlci].state = DISCONNECTED;
2091 + wake_up_interruptible(&ts0710->dlci[dlci].
2093 + wake_up_interruptible(&ts0710->dlci[dlci].
2095 + ts0710_reset_dlci(dlci);
2098 + (" Something wrong receiving UA packet\n");
2101 + TS0710_DEBUG("invalid dlci %d\n", dlci);
2107 + TS0710_DEBUG("DM packet received\n");
2109 +/*For BP UART problem
2110 + if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
2115 + TS0710_DEBUG("server channel == 0\n");
2117 + if (ts0710->dlci[0].state == CONNECTING) {
2118 + be_connecting = 1;
2120 + be_connecting = 0;
2122 + ts0710_upon_disconnect();
2123 + if (be_connecting) {
2124 + ts0710->dlci[0].state = REJECTED;
2126 + } else if (valid_dlci(dlci)) {
2127 + TS0710_DEBUG("Incomming DM on channel %d\n", dlci);
2129 + if (ts0710->dlci[dlci].state == CONNECTING) {
2130 + ts0710->dlci[dlci].state = REJECTED;
2132 + ts0710->dlci[dlci].state = DISCONNECTED;
2134 + wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
2135 + wake_up_interruptible(&ts0710->dlci[dlci].close_wait);
2136 + ts0710_reset_dlci(dlci);
2138 + TS0710_DEBUG("invalid dlci %d\n", dlci);
2144 + TS0710_DEBUG("DISC packet received\n");
2146 +/*For BP UART problem
2147 + if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
2152 + TS0710_DEBUG("server channel == 0\n");
2154 + send_ua(ts0710, dlci);
2155 + TS0710_DEBUG("DISC, sending back UA\n");
2157 + ts0710_upon_disconnect();
2158 + } else if (valid_dlci(dlci)) {
2159 + TS0710_DEBUG("Incomming DISC on channel %d\n", dlci);
2161 + send_ua(ts0710, dlci);
2162 + TS0710_DEBUG("DISC, sending back UA\n");
2164 + ts0710->dlci[dlci].state = DISCONNECTED;
2165 + wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
2166 + wake_up_interruptible(&ts0710->dlci[dlci].close_wait);
2167 + ts0710_reset_dlci(dlci);
2169 + TS0710_DEBUG("invalid dlci %d\n", dlci);
2175 + TS0710_DEBUG("UIH packet received\n");
2177 + if ((dlci >= TS0710_MAX_CHN)) {
2178 + TS0710_DEBUG("invalid dlci %d\n", dlci);
2179 + send_dm(ts0710, dlci);
2183 + if (GET_PF(short_pkt->h.control)) {
2185 + ("MUX Error %s: UIH packet with P/F set, discard it!\n",
2190 + if ((ts0710->dlci[dlci].state != CONNECTED)
2191 + && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
2193 + ("MUX Error %s: DLCI %d not connected, discard it!\n",
2194 + __FUNCTION__, dlci);
2195 + send_dm(ts0710, dlci);
2199 + if ((short_pkt->h.length.ea) == 0) {
2200 + TS0710_DEBUG("Long UIH packet received\n");
2201 + long_pkt = (long_frame *) data;
2202 + uih_len = GET_LONG_LENGTH(long_pkt->h.length);
2203 + uih_data_start = long_pkt->h.data;
2204 + TS0710_DEBUG("long packet length %d\n", uih_len);
2206 +/*For BP UART problem
2207 + if (crc_check(data, LONG_CRC_CHECK, *(uih_data_start + uih_len)))
2211 + TS0710_DEBUG("Short UIH pkt received\n");
2212 + uih_len = short_pkt->h.length.len;
2213 + uih_data_start = short_pkt->data;
2215 +/*For BP UART problem
2216 + if (crc_check(data, SHORT_CRC_CHECK, *(uih_data_start + uih_len)))
2222 + TS0710_DEBUG("UIH on serv_channel 0\n");
2223 + process_mcc(data, len, ts0710,
2224 + !(short_pkt->h.length.ea));
2225 + } else if (valid_dlci(dlci)) {
2226 + /* do tty dispatch */
2229 + struct tty_struct *tty;
2232 + __u8 flow_control;
2233 + mux_recv_struct *recv_info;
2235 + mux_recv_packet *recv_packet, *recv_packet2;
2237 + TS0710_DEBUG("UIH on channel %d\n", dlci);
2239 + if (uih_len > ts0710->dlci[dlci].mtu) {
2241 + ("MUX Error: DLCI:%d, uih_len:%d is bigger than mtu:%d, discard data!\n",
2242 + dlci, uih_len, ts0710->dlci[dlci].mtu);
2246 + tag = *uih_data_start;
2256 + tty_idx = dlci2tty[dlci].cmdtty;
2257 + TS0710_DEBUG("CMDTAG on DLCI:%d, /dev/mux%d\n",
2259 + TS0710_DEBUGSTR(uih_data_start, uih_len);
2260 + if (!(iscmdtty[tty_idx])) {
2262 + ("MUX Error: %s: Wrong CMDTAG on DLCI:%d, /dev/mux%d\n",
2263 + __FUNCTION__, dlci, tty_idx);
2268 + tty_idx = dlci2tty[dlci].datatty;
2270 + ("NON-CMDTAG on DLCI:%d, /dev/mux%d\n",
2272 + if (iscmdtty[tty_idx]) {
2274 + ("MUX Error: %s: Wrong NON-CMDTAG on DLCI:%d, /dev/mux%d\n",
2275 + __FUNCTION__, dlci, tty_idx);
2279 + tty = mux_table[tty_idx];
2280 + if ((!mux_tty[tty_idx]) || (!tty)) {
2282 + ("MUX: No application waiting for, discard it! /dev/mux%d\n",
2284 + } else { /* Begin processing received data */
2285 + if ((!mux_recv_info_flags[tty_idx])
2286 + || (!mux_recv_info[tty_idx])) {
2288 + ("MUX Error: No mux_recv_info, discard it! /dev/mux%d\n",
2293 + recv_info = mux_recv_info[tty_idx];
2294 + if (recv_info->total > 8192) {
2296 + ("MUX : discard data for tty_idx:%d, recv_info->total > 8192 \n",
2304 + recv_room = 65535;
2305 + if (tty->receive_room)
2306 + recv_room = tty->receive_room;
2308 + if (test_bit(TTY_THROTTLED, &tty->flags)) {
2312 + (TTY_DONT_FLIP, &tty->flags)) {
2315 + } else if (recv_info->total) {
2318 + } else if (recv_room < uih_len) {
2324 + (uih_len + recv_info->total)) <
2325 + ts0710->dlci[dlci].mtu) {
2330 + if (!queue_data) {
2331 + /* Put received data into read buffer of tty */
2333 + ("Put received data into read buffer of /dev/mux%d",
2340 + (tty->ldisc.receive_buf) (tty,
2347 + ("tty->ldisc.receive_buf take ticks: %lu",
2351 + } else { /* Queue data */
2354 + ("Put received data into recv queue of /dev/mux%d",
2356 + if (recv_info->total) {
2357 + /* recv_info is already linked into mux_recv_queue */
2360 + get_mux_recv_packet
2362 + if (!recv_packet) {
2364 + ("MUX %s: no memory\n",
2369 + memcpy(recv_packet->data,
2370 + uih_data_start, uih_len);
2371 + recv_packet->length = uih_len;
2372 + recv_info->total += uih_len;
2373 + recv_packet->next = NULL;
2375 + if (!(recv_info->mux_packet)) {
2376 + recv_info->mux_packet =
2382 + while (recv_packet2->
2388 + recv_packet2->next =
2390 + } /* End if( !(recv_info->mux_packet) ) */
2391 + } else { /* recv_info->total == 0 */
2393 + TS0710MUX_RECV_BUF_SIZE) {
2395 + ("MUX Error: tty_idx:%d, uih_len == %d is too big\n",
2396 + tty_idx, uih_len);
2398 + TS0710MUX_RECV_BUF_SIZE;
2400 + memcpy(recv_info->data,
2401 + uih_data_start, uih_len);
2402 + recv_info->length = uih_len;
2403 + recv_info->total = uih_len;
2405 + add_post_recv_queue
2408 + } /* End recv_info->total == 0 */
2409 + } /* End Queue data */
2411 + if (flow_control) {
2412 + /* Do something for flow control */
2413 + ts0710_flow_off(tty, dlci, ts0710);
2417 + dlci2tty[TS0710MUX_GPRS1_DLCI].datatty) {
2419 + (TS0710MUX_GPRS1_RECV_COUNT_IDX,
2421 + post_recv_count_flag = 1;
2424 + [TS0710MUX_GPRS1_RECV_COUNT_IDX]
2427 + } else if (tty_idx ==
2428 + dlci2tty[TS0710MUX_GPRS2_DLCI].
2431 + (TS0710MUX_GPRS2_RECV_COUNT_IDX,
2433 + post_recv_count_flag = 1;
2436 + [TS0710MUX_GPRS2_RECV_COUNT_IDX]
2442 + schedule_work(&post_recv_tqueue);
2443 + } /* End processing received data */
2445 + TS0710_DEBUG("invalid dlci %d\n", dlci);
2451 + TS0710_DEBUG("illegal packet\n");
2458 +int ts0710_send_data(ts0710_con *ts0710, __u8 dlci, __u8 *data, __u32 count)
2460 + __u32 c, total = 0;
2463 + if( ts0710->dlci[0].state == FLOW_STOPPED ){
2464 + TS0710_DEBUG("Flow stopped on all channels, returning zero\n");
2467 + return -EFLOWSTOPPED;
2468 + } else if( ts0710->dlci[dlci].state == FLOW_STOPPED ){
2469 + TS0710_DEBUG("Flow stopped, returning zero\n");
2472 + return -EFLOWSTOPPED;
2473 + } else if( ts0710->dlci[dlci].state == CONNECTED ){
2475 + TS0710_DEBUG("trying to send %d bytes\n", count);
2479 + /* The first byte is always a Cmd/Data tag */
2481 + while( count > 1 ){
2483 + c = min(count, ts0710->dlci[dlci].mtu);
2484 + if( queue_uih(data, c, ts0710, dlci) <= 0 ) {
2498 + TS0710_DEBUG("sent %d bytes\n", total);
2501 + TS0710_DEBUG("DLCI %d not connected\n", dlci);
2502 + return -EDISCONNECTED;
2507 +/* Close ts0710 channel */
2508 +static void ts0710_close_channel(__u8 dlci)
2510 + ts0710_con *ts0710 = &ts0710_connection;
2514 + TS0710_DEBUG("ts0710_disc_command on channel %d\n", dlci);
2516 + if ((ts0710->dlci[dlci].state == DISCONNECTED)
2517 + || (ts0710->dlci[dlci].state == REJECTED)) {
2519 + } else if (ts0710->dlci[dlci].state == DISCONNECTING) {
2523 + ts0710->dlci[dlci].state = DISCONNECTING;
2527 + send_disc(ts0710, dlci);
2528 + interruptible_sleep_on_timeout(&ts0710->dlci[dlci].
2530 + TS0710MUX_TIME_OUT);
2531 + if (ts0710->dlci[dlci].state == DISCONNECTED) {
2533 + } else if (signal_pending(current)) {
2535 + ("MUX DLCI %d Send DISC got signal!\n",
2538 + } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2540 + ("MUX DLCI %d Send DISC timeout!\n", dlci);
2545 + if (ts0710->dlci[dlci].state != DISCONNECTED) {
2546 + if (dlci == 0) { /* Control Channel */
2547 + ts0710_upon_disconnect();
2548 + } else { /* Other Channel */
2549 + ts0710->dlci[dlci].state = DISCONNECTED;
2550 + wake_up_interruptible(&ts0710->dlci[dlci].
2552 + ts0710_reset_dlci(dlci);
2558 +int ts0710_open_channel(__u8 dlci)
2560 + ts0710_con *ts0710 = &ts0710_connection;
2566 + if (dlci == 0) { // control channel
2567 + if ((ts0710->dlci[0].state == CONNECTED)
2568 + || (ts0710->dlci[0].state == FLOW_STOPPED)) {
2570 + } else if (ts0710->dlci[0].state == CONNECTING) {
2573 + ("MUX DLCI: 0, reentry to open DLCI 0, pid: %d, %s !\n",
2574 + current->pid, current->comm);
2578 + interruptible_sleep_on_timeout(&ts0710->dlci[0].
2580 + TS0710MUX_TIME_OUT);
2581 + if ((ts0710->dlci[0].state == CONNECTED)
2582 + || (ts0710->dlci[0].state ==
2586 + } else if (ts0710->dlci[0].state == REJECTED) {
2587 + retval = -EREJECTED;
2589 + } else if (ts0710->dlci[0].state ==
2592 + } else if (signal_pending(current)) {
2594 + ("MUX DLCI:%d Wait for connecting got signal!\n",
2598 + } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2600 + ("MUX DLCI:%d Wait for connecting timeout!\n",
2603 + } else if (ts0710->dlci[0].state == CONNECTING) {
2608 + if (ts0710->dlci[0].state == CONNECTING) {
2609 + ts0710->dlci[0].state = DISCONNECTED;
2611 + } else if ((ts0710->dlci[0].state != DISCONNECTED)
2612 + && (ts0710->dlci[0].state != REJECTED)) {
2613 + TS0710_PRINTK("MUX DLCI:%d state is invalid!\n", dlci);
2616 + ts0710->initiator = 1;
2617 + ts0710->dlci[0].state = CONNECTING;
2618 + ts0710->dlci[0].initiator = 1;
2622 + send_sabm(ts0710, 0);
2623 + interruptible_sleep_on_timeout(&ts0710->dlci[0].
2625 + TS0710MUX_TIME_OUT);
2626 + if ((ts0710->dlci[0].state == CONNECTED)
2627 + || (ts0710->dlci[0].state ==
2631 + } else if (ts0710->dlci[0].state == REJECTED) {
2633 + ("MUX DLCI:%d Send SABM got rejected!\n",
2635 + retval = -EREJECTED;
2637 + } else if (signal_pending(current)) {
2639 + ("MUX DLCI:%d Send SABM got signal!\n",
2643 + } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2645 + ("MUX DLCI:%d Send SABM timeout!\n",
2651 + if (ts0710->dlci[0].state == CONNECTING) {
2652 + ts0710->dlci[0].state = DISCONNECTED;
2654 + wake_up_interruptible(&ts0710->dlci[0].open_wait);
2656 + } else { // other channel
2657 + if ((ts0710->dlci[0].state != CONNECTED)
2658 + && (ts0710->dlci[0].state != FLOW_STOPPED)) {
2660 + } else if ((ts0710->dlci[dlci].state == CONNECTED)
2661 + || (ts0710->dlci[dlci].state == FLOW_STOPPED)) {
2663 + } else if ((ts0710->dlci[dlci].state == NEGOTIATING)
2664 + || (ts0710->dlci[dlci].state == CONNECTING)) {
2669 + interruptible_sleep_on_timeout(&ts0710->
2672 + TS0710MUX_TIME_OUT);
2673 + if ((ts0710->dlci[dlci].state == CONNECTED)
2674 + || (ts0710->dlci[dlci].state ==
2678 + } else if (ts0710->dlci[dlci].state == REJECTED) {
2679 + retval = -EREJECTED;
2681 + } else if (ts0710->dlci[dlci].state ==
2684 + } else if (signal_pending(current)) {
2686 + ("MUX DLCI:%d Wait for connecting got signal!\n",
2690 + } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2692 + ("MUX DLCI:%d Wait for connecting timeout!\n",
2696 + if ((ts0710->dlci[dlci].state ==
2698 + || (ts0710->dlci[dlci].state ==
2704 + if ((ts0710->dlci[dlci].state == NEGOTIATING)
2705 + || (ts0710->dlci[dlci].state == CONNECTING)) {
2706 + ts0710->dlci[dlci].state = DISCONNECTED;
2708 + } else if ((ts0710->dlci[dlci].state != DISCONNECTED)
2709 + && (ts0710->dlci[dlci].state != REJECTED)) {
2710 + TS0710_PRINTK("MUX DLCI:%d state is invalid!\n", dlci);
2713 + ts0710->dlci[dlci].state = NEGOTIATING;
2714 + ts0710->dlci[dlci].initiator = 1;
2718 + send_pn_msg(ts0710, 7, ts0710->dlci[dlci].mtu,
2720 + interruptible_sleep_on_timeout(&ts0710->
2723 + TS0710MUX_TIME_OUT);
2724 + if (ts0710->dlci[dlci].state == CONNECTING) {
2726 + } else if (signal_pending(current)) {
2728 + ("MUX DLCI:%d Send pn_msg got signal!\n",
2732 + } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2734 + ("MUX DLCI:%d Send pn_msg timeout!\n",
2740 + if (ts0710->dlci[dlci].state == CONNECTING) {
2744 + send_sabm(ts0710, dlci);
2745 + interruptible_sleep_on_timeout(&ts0710->
2749 + TS0710MUX_TIME_OUT);
2750 + if ((ts0710->dlci[dlci].state ==
2752 + || (ts0710->dlci[dlci].state ==
2756 + } else if (ts0710->dlci[dlci].state ==
2759 + ("MUX DLCI:%d Send SABM got rejected!\n",
2761 + retval = -EREJECTED;
2763 + } else if (signal_pending(current)) {
2765 + ("MUX DLCI:%d Send SABM got signal!\n",
2769 + } else if ((jiffies - t) >=
2770 + TS0710MUX_TIME_OUT) {
2772 + ("MUX DLCI:%d Send SABM timeout!\n",
2779 + if ((ts0710->dlci[dlci].state == NEGOTIATING)
2780 + || (ts0710->dlci[dlci].state == CONNECTING)) {
2781 + ts0710->dlci[dlci].state = DISCONNECTED;
2783 + wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
2789 +static int ts0710_exec_test_cmd(void)
2791 + ts0710_con *ts0710 = &ts0710_connection;
2792 + __u8 *f_buf; /* Frame buffer */
2793 + __u8 *d_buf; /* Data buffer */
2794 + int retval = -EFAULT;
2798 + if (ts0710->be_testing) {
2801 + interruptible_sleep_on_timeout(&ts0710->test_wait,
2802 + 3 * TS0710MUX_TIME_OUT);
2803 + if (ts0710->be_testing == 0) {
2804 + if (ts0710->test_errs == 0) {
2809 + } else if (signal_pending(current)) {
2811 + ("Wait for Test_cmd response got signal!\n");
2813 + } else if ((jiffies - t) >= 3 * TS0710MUX_TIME_OUT) {
2814 + TS0710_DEBUG("Wait for Test_cmd response timeout!\n");
2818 + ts0710->be_testing = 1; /* Set the flag */
2820 + f_buf = (__u8 *) kmalloc(TEST_PATTERN_SIZE + 32, GFP_KERNEL);
2821 + d_buf = (__u8 *) kmalloc(TEST_PATTERN_SIZE + 32, GFP_KERNEL);
2822 + if ((!f_buf) || (!d_buf)) {
2830 + ts0710->be_testing = 0; /* Clear the flag */
2831 + ts0710->test_errs = TEST_PATTERN_SIZE;
2832 + wake_up_interruptible(&ts0710->test_wait);
2836 + for (j = 0; j < TEST_PATTERN_SIZE; j++) {
2837 + d_buf[j] = j & 0xFF;
2841 + ts0710_test_msg(ts0710, d_buf, TEST_PATTERN_SIZE, MCC_CMD,
2843 + interruptible_sleep_on_timeout(&ts0710->test_wait,
2844 + 2 * TS0710MUX_TIME_OUT);
2845 + if (ts0710->be_testing == 0) {
2846 + if (ts0710->test_errs == 0) {
2851 + } else if (signal_pending(current)) {
2852 + TS0710_DEBUG("Send Test_cmd got signal!\n");
2854 + } else if ((jiffies - t) >= 2 * TS0710MUX_TIME_OUT) {
2855 + TS0710_DEBUG("Send Test_cmd timeout!\n");
2856 + ts0710->test_errs = TEST_PATTERN_SIZE;
2860 + ts0710->be_testing = 0; /* Clear the flag */
2861 + wake_up_interruptible(&ts0710->test_wait);
2863 + /* Release buffer */
2875 +static void mux_sched_send(void)
2879 + schedule_work(&send_tqueue);
2881 + if (!tq_serial_for_mux) {
2882 + TS0710_PRINTK("MUX Error: %s: tq_serial_for_mux == 0\n",
2886 + schedule_work(&send_tqueue);
2887 + mark_bh(SERIAL_BH);
2892 +/****************************
2893 + * TTY driver routines
2894 +*****************************/
2896 +static void mux_close(struct tty_struct *tty, struct file *filp)
2898 + ts0710_con *ts0710 = &ts0710_connection;
2904 + UNUSED_PARAM(filp);
2909 + line = tty->index;
2910 + if ((line < 0) || (line >= NR_MUXS)) {
2913 + if (mux_tty[line] > 0)
2916 + dlci = tty2dlci[line];
2917 + cmdtty = dlci2tty[dlci].cmdtty;
2918 + datatty = dlci2tty[dlci].datatty;
2919 + if ((mux_tty[cmdtty] == 0) && (mux_tty[datatty] == 0)) {
2921 + ts0710_close_channel(0);
2923 + ("MUX mux_close: tapisrv might be down!!! Close DLCI 1\n");
2924 + TS0710_SIG2APLOGD();
2926 + ts0710_close_channel(dlci);
2929 + if (mux_tty[line] == 0) {
2930 + if ((mux_send_info_flags[line])
2931 + && (mux_send_info[line])
2932 + /*&& (mux_send_info[line]->filled == 0) */
2934 + mux_send_info_flags[line] = 0;
2935 + kfree(mux_send_info[line]);
2936 + mux_send_info[line] = 0;
2937 + TS0710_DEBUG("Free mux_send_info for /dev/mux%d", line);
2940 + if ((mux_recv_info_flags[line])
2941 + && (mux_recv_info[line])
2942 + && (mux_recv_info[line]->total == 0)) {
2943 + mux_recv_info_flags[line] = 0;
2944 + free_mux_recv_struct(mux_recv_info[line]);
2945 + mux_recv_info[line] = 0;
2946 + TS0710_DEBUG("Free mux_recv_info for /dev/mux%d", line);
2949 + ts0710_flow_on(dlci, ts0710);
2950 + schedule_work(&post_recv_tqueue);
2952 + wake_up_interruptible(&tty->read_wait);
2953 + wake_up_interruptible(&tty->write_wait);
2958 +static void mux_throttle(struct tty_struct *tty)
2960 + ts0710_con *ts0710 = &ts0710_connection;
2969 + line = tty->index;
2970 + if ((line < 0) || (line >= NR_MUXS)) {
2974 + TS0710_DEBUG("Enter into %s, minor number is: %d\n", __FUNCTION__,
2977 + dlci = tty2dlci[line];
2978 + if ((ts0710->dlci[0].state != CONNECTED)
2979 + && (ts0710->dlci[0].state != FLOW_STOPPED)) {
2981 + } else if ((ts0710->dlci[dlci].state != CONNECTED)
2982 + && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
2986 + if (ts0710->dlci[dlci].flow_control) {
2990 + for (i = 0; i < 3; i++) {
2991 + if (ts0710_msc_msg
2992 + (ts0710, EA | FC | RTC | RTR | DV, MCC_CMD, dlci) < 0) {
2995 + TS0710_LOG("MUX Send Flow off on dlci %d\n", dlci);
2996 + ts0710->dlci[dlci].flow_control = 1;
3002 +static void mux_unthrottle(struct tty_struct *tty)
3004 + ts0710_con *ts0710 = &ts0710_connection;
3007 + mux_recv_struct *recv_info;
3012 + line = tty->index;
3013 + if ((line < 0) || (line >= NR_MUXS)) {
3017 + if ((!mux_recv_info_flags[line]) || (!mux_recv_info[line])) {
3021 + TS0710_DEBUG("Enter into %s, minor number is: %d\n", __FUNCTION__,
3024 + recv_info = mux_recv_info[line];
3025 + dlci = tty2dlci[line];
3027 + if (recv_info->total) {
3028 + recv_info->post_unthrottle = 1;
3029 + schedule_work(&post_recv_tqueue);
3031 + ts0710_flow_on(dlci, ts0710);
3035 +static int mux_chars_in_buffer(struct tty_struct *tty)
3037 + ts0710_con *ts0710 = &ts0710_connection;
3041 + mux_send_struct *send_info;
3043 + retval = TS0710MUX_MAX_CHARS_IN_BUF;
3047 + line = tty->index;
3048 + if ((line < 0) || (line >= NR_MUXS)) {
3052 + dlci = tty2dlci[line];
3053 + if (ts0710->dlci[0].state == FLOW_STOPPED) {
3055 + ("Flow stopped on all channels, returning MAX chars in buffer\n");
3057 + } else if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
3058 + TS0710_DEBUG("Flow stopped, returning MAX chars in buffer\n");
3060 + } else if (ts0710->dlci[dlci].state != CONNECTED) {
3061 + TS0710_DEBUG("DLCI %d not connected\n", dlci);
3065 + if (!(mux_send_info_flags[line])) {
3068 + send_info = mux_send_info[line];
3072 + if (send_info->filled) {
3082 +static int mux_chars_in_serial_buffer(struct tty_struct *tty)
3084 + UNUSED_PARAM(tty);
3086 + if ((COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)) {
3088 + ("MUX %s: (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)\n",
3091 +#ifndef USB_FOR_MUX
3093 + ("MUX %s: tapisrv might be down!!! (serial_for_mux_driver == 0) || (serial_for_mux_tty == 0)\n",
3095 + TS0710_SIG2APLOGD();
3100 + return COMM_FOR_MUX_DRIVER->chars_in_buffer(COMM_FOR_MUX_TTY);
3103 +static int mux_write(struct tty_struct *tty,
3104 + const unsigned char *buf, int count)
3106 + ts0710_con *ts0710 = &ts0710_connection;
3109 + mux_send_struct *send_info;
3122 + line = tty->index;
3123 + if ((line < 0) || (line >= NR_MUXS))
3126 + dlci = tty2dlci[line];
3127 + if (ts0710->dlci[0].state == FLOW_STOPPED) {
3129 + ("Flow stopped on all channels, returning zero /dev/mux%d\n",
3132 + } else if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
3133 + TS0710_DEBUG("Flow stopped, returning zero /dev/mux%d\n", line);
3135 + } else if (ts0710->dlci[dlci].state == CONNECTED) {
3137 + if (!(mux_send_info_flags[line])) {
3139 + ("MUX Error: mux_write: mux_send_info_flags[%d] == 0\n",
3143 + send_info = mux_send_info[line];
3146 + ("MUX Error: mux_write: mux_send_info[%d] == 0\n",
3151 + c = min(count, (ts0710->dlci[dlci].mtu - 1));
3156 + if (test_and_set_bit(BUF_BUSY, &send_info->flags))
3159 + if (send_info->filled) {
3160 + clear_bit(BUF_BUSY, &send_info->flags);
3164 + d_buf = ((__u8 *) send_info->buf) + TS0710MUX_SEND_BUF_OFFSET;
3165 + memcpy(&d_buf[1], buf, c);
3167 + TS0710_DEBUG("Prepare to send %d bytes from /dev/mux%d", c,
3169 + if (iscmdtty[line]) {
3170 + TS0710_DEBUGSTR(&d_buf[1], c);
3171 + TS0710_DEBUG("CMDTAG");
3172 + d_buf[0] = CMDTAG;
3174 + TS0710_DEBUG("DATATAG");
3175 + d_buf[0] = DATATAG;
3178 + TS0710_DEBUGHEX(d_buf, c + 1);
3180 + send_info->frame = d_buf;
3181 + queue_uih(send_info, c + 1, ts0710, dlci);
3182 + send_info->filled = 1;
3183 + clear_bit(BUF_BUSY, &send_info->flags);
3186 + if (dlci == TS0710MUX_GPRS1_DLCI) {
3188 + (TS0710MUX_GPRS1_SEND_COUNT_IDX, c) < 0) {
3189 + post_recv_count_flag = 1;
3191 + mux_data_count2[TS0710MUX_GPRS1_SEND_COUNT_IDX]
3194 + } else if (dlci == TS0710MUX_GPRS2_DLCI) {
3196 + (TS0710MUX_GPRS2_SEND_COUNT_IDX, c) < 0) {
3197 + post_recv_count_flag = 1;
3199 + mux_data_count2[TS0710MUX_GPRS2_SEND_COUNT_IDX]
3205 + schedule_work(&post_recv_tqueue);
3207 + if (mux_chars_in_serial_buffer(COMM_FOR_MUX_TTY) == 0) {
3208 + /* Sending bottom half should be
3209 + run after return from this function */
3214 + TS0710_PRINTK("MUX mux_write: DLCI %d not connected\n", dlci);
3215 + return -EDISCONNECTED;
3219 +static int mux_write_room(struct tty_struct *tty)
3221 + ts0710_con *ts0710 = &ts0710_connection;
3225 + mux_send_struct *send_info;
3231 + line = tty->index;
3232 + if ((line < 0) || (line >= NR_MUXS)) {
3236 + dlci = tty2dlci[line];
3237 + if (ts0710->dlci[0].state == FLOW_STOPPED) {
3238 + TS0710_DEBUG("Flow stopped on all channels, returning ZERO\n");
3240 + } else if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
3241 + TS0710_DEBUG("Flow stopped, returning ZERO\n");
3243 + } else if (ts0710->dlci[dlci].state != CONNECTED) {
3244 + TS0710_DEBUG("DLCI %d not connected\n", dlci);
3248 + if (!(mux_send_info_flags[line])) {
3251 + send_info = mux_send_info[line];
3255 + if (send_info->filled) {
3259 + retval = ts0710->dlci[dlci].mtu - 1;
3265 +static int mux_ioctl(struct tty_struct *tty, struct file *file,
3266 + unsigned int cmd, unsigned long arg)
3268 + ts0710_con *ts0710 = &ts0710_connection;
3272 + UNUSED_PARAM(file);
3273 + UNUSED_PARAM(arg);
3278 + line = tty->index;
3279 + if ((line < 0) || (line >= NR_MUXS)) {
3283 + dlci = tty2dlci[line];
3285 + case TS0710MUX_IO_MSC_HANGUP:
3286 + if (ts0710_msc_msg(ts0710, EA | RTR | DV, MCC_CMD, dlci) < 0) {
3292 + case TS0710MUX_IO_TEST_CMD:
3293 + return ts0710_exec_test_cmd();
3295 + case TS0710MUX_IO_DLCI_FC_ON:
3299 + if( ts0710_msc_msg(ts0710, EA | RTC | RTR | DV, MCC_CMD, (__u8)line) < 0) {
3305 + case TS0710MUX_IO_DLCI_FC_OFF:
3309 + if( ts0710_msc_msg(ts0710, EA | FC | RTC | RTR | DV, MCC_CMD, (__u8)line) < 0) {
3315 + case TS0710MUX_IO_FC_ON:
3319 + if( ts0710_fcon_msg(ts0710, MCC_CMD) < 0) {
3325 + case TS0710MUX_IO_FC_OFF:
3329 + if( ts0710_fcoff_msg(ts0710, MCC_CMD) < 0) {
3338 + return -ENOIOCTLCMD;
3341 +static void mux_flush_buffer(struct tty_struct *tty)
3349 + line = tty->index;
3350 + if ((line < 0) || (line >= NR_MUXS)) {
3354 + TS0710_PRINTK("MUX %s: line is:%d\n", __FUNCTION__, line);
3356 + if ((mux_send_info_flags[line])
3357 + && (mux_send_info[line])
3358 + && (mux_send_info[line]->filled)) {
3360 + mux_send_info[line]->filled = 0;
3363 + wake_up_interruptible(&tty->write_wait);
3364 +#ifdef SERIAL_HAVE_POLL_WAIT
3365 + wake_up_interruptible(&tty->poll_wait);
3367 + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
3368 + tty->ldisc.write_wakeup) {
3369 + (tty->ldisc.write_wakeup) (tty);
3373 + if( (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0) ) {
3374 + TS0710_PRINTK("MUX %s: (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)\n", __FUNCTION__);
3376 +#ifndef USB_FOR_MUX
3377 + TS0710_PRINTK("MUX %s: tapisrv might be down!!! (serial_for_mux_driver == 0) || (serial_for_mux_tty == 0)\n", __FUNCTION__);
3378 + TS0710_SIG2APLOGD();
3383 + return COMM_FOR_MUX_DRIVER->flush_buffer(COMM_FOR_MUX_TTY);
3387 +static int mux_open(struct tty_struct *tty, struct file *filp)
3394 + mux_send_struct *send_info;
3395 + mux_recv_struct *recv_info;
3397 + UNUSED_PARAM(filp);
3400 + if ((COMM_FOR_MUX_DRIVER == NULL) || (COMM_FOR_MUX_TTY == NULL)) {
3403 + TS0710_PRINTK("MUX: please install and open IPC-USB first\n");
3405 + TS0710_PRINTK("MUX: please install and open ttyS0 first\n");
3414 + line = tty->index;
3415 + if ((line < 0) || (line >= NR_MUXS)) {
3418 +#ifdef TS0710SERVER
3419 + /* do nothing as a server */
3424 + dlci = tty2dlci[line];
3426 +/* if( dlci == 1 ) { */
3427 + /* Open server channel 0 first */
3428 + if ((retval = ts0710_open_channel(0)) != 0) {
3429 + TS0710_PRINTK("MUX: Can't connect server channel 0!\n");
3437 + /* Allocate memory first. As soon as connection has been established, MUX may receive */
3438 + if (mux_send_info_flags[line] == 0) {
3440 + (mux_send_struct *) kmalloc(sizeof(mux_send_struct),
3448 + send_info->length = 0;
3449 + send_info->flags = 0;
3450 + send_info->filled = 0;
3451 + mux_send_info[line] = send_info;
3452 + mux_send_info_flags[line] = 1;
3453 + TS0710_DEBUG("Allocate mux_send_info for /dev/mux%d", line);
3456 + if (mux_recv_info_flags[line] == 0) {
3458 + (mux_recv_struct *) kmalloc(sizeof(mux_recv_struct),
3461 + mux_send_info_flags[line] = 0;
3462 + kfree(mux_send_info[line]);
3463 + mux_send_info[line] = 0;
3464 + TS0710_DEBUG("Free mux_send_info for /dev/mux%d", line);
3470 + recv_info->length = 0;
3471 + recv_info->total = 0;
3472 + recv_info->mux_packet = 0;
3473 + recv_info->next = 0;
3474 + recv_info->no_tty = line;
3475 + recv_info->post_unthrottle = 0;
3476 + mux_recv_info[line] = recv_info;
3477 + mux_recv_info_flags[line] = 1;
3478 + TS0710_DEBUG("Allocate mux_recv_info for /dev/mux%d", line);
3481 + /* Now establish DLCI connection */
3482 + cmdtty = dlci2tty[dlci].cmdtty;
3483 + datatty = dlci2tty[dlci].datatty;
3484 + if ((mux_tty[cmdtty] > 0) || (mux_tty[datatty] > 0)) {
3485 + if ((retval = ts0710_open_channel(dlci)) != 0) {
3486 + TS0710_PRINTK("MUX: Can't connected channel %d!\n",
3488 + ts0710_reset_dlci(dlci);
3490 + mux_send_info_flags[line] = 0;
3491 + kfree(mux_send_info[line]);
3492 + mux_send_info[line] = 0;
3493 + TS0710_DEBUG("Free mux_send_info for /dev/mux%d", line);
3495 + mux_recv_info_flags[line] = 0;
3496 + free_mux_recv_struct(mux_recv_info[line]);
3497 + mux_recv_info[line] = 0;
3498 + TS0710_DEBUG("Free mux_recv_info for /dev/mux%d", line);
3511 +/* mux dispatcher, call from serial.c receiver_chars() */
3512 +void mux_dispatcher(struct tty_struct *tty)
3514 + UNUSED_PARAM(tty);
3516 + schedule_work(&receive_tqueue);
3519 +/*For BP UART problem Begin*/
3521 +static int send_ack(ts0710_con * ts0710, __u8 seq_num, __u8 bp_seq1,
3524 +static int send_ack(ts0710_con * ts0710, __u8 seq_num)
3531 + static __u16 ack_seq = 0;
3534 + ack = (short_frame *) (buf + 1);
3535 + ack->h.addr.ea = 1;
3536 + ack->h.addr.cr = ((ts0710->initiator) & 0x1);
3537 + ack->h.addr.d = 0;
3538 + ack->h.addr.server_chn = 0;
3539 + ack->h.control = ACK;
3540 + ack->h.length.ea = 1;
3543 + ack->h.length.len = 5;
3544 + ack->data[0] = seq_num;
3545 + ack->data[1] = bp_seq1;
3546 + ack->data[2] = bp_seq2;
3547 + ack->data[3] = (ack_seq & 0xFF);
3548 + ack->data[4] = (ack_seq >> 8) & 0xFF;
3550 + ack->data[5] = crc_calc((__u8 *) ack, SHORT_CRC_CHECK);
3552 + ack->h.length.len = 1;
3553 + ack->data[0] = seq_num;
3554 + ack->data[1] = crc_calc((__u8 *) ack, SHORT_CRC_CHECK);
3557 + return basic_write(ts0710, buf,
3558 + (sizeof(short_frame) + FCS_SIZE +
3559 + ack->h.length.len));
3562 +/*For BP UART problem End*/
3564 +static void receive_worker(void *private_)
3566 + struct tty_struct *tty = COMM_FOR_MUX_TTY;
3568 + static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE];
3569 + static unsigned char *tbuf_ptr = &tbuf[0];
3570 + static unsigned char *start_flag = 0;
3571 + unsigned char *search, *to, *from;
3572 + short_frame *short_pkt;
3573 + long_frame *long_pkt;
3574 + static int framelen = -1;
3576 + /*For BP UART problem Begin */
3577 + static __u8 expect_seq = 0;
3579 + __u8 *uih_data_start;
3581 + /*For BP UART problem End */
3583 + UNUSED_PARAM(private_);
3589 + TS0710_DEBUG("Receive following bytes from IPC-USB");
3591 + TS0710_DEBUG("Receive following bytes from UART");
3594 + TS0710_DEBUGHEX(cp, count);
3596 + if (count > (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf))) {
3598 + ("MUX receive_worker: !!!!! Exceed buffer boundary !!!!!\n");
3599 + count = (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf));
3602 + count = tty_buffer_request_room(tty, count);
3604 + for (i = 0; i < count; i++)
3605 + tty_insert_flip_char(tty, tbuf_ptr[i], TTY_NORMAL);
3607 + tbuf_ptr += count;
3608 + search = &tbuf[0];
3610 + if (test_and_set_bit(RECV_RUNNING, &mux_recv_flags)) {
3611 + schedule_work(&receive_tqueue);
3615 + if ((start_flag != 0) && (framelen != -1)) {
3616 + if ((tbuf_ptr - start_flag) < framelen) {
3617 + clear_bit(RECV_RUNNING, &mux_recv_flags);
3623 + if (start_flag == 0) { /* Frame Start Flag not found */
3625 + while (search < tbuf_ptr) {
3626 + if (*search == TS0710_BASIC_FLAG) {
3627 + start_flag = search;
3632 + TS0710_LOG(">S %02x %c\n", *search,
3640 + if (start_flag == 0) {
3641 + tbuf_ptr = &tbuf[0];
3644 + } else { /* Frame Start Flag found */
3645 + /* 1 start flag + 1 address + 1 control + 1 or 2 length + lengths data + 1 FCS + 1 end flag */
3646 + /* For BP UART problem 1 start flag + 1 seq_num + 1 address + ...... */
3647 + /*if( (framelen == -1) && ((tbuf_ptr - start_flag) > TS0710_MAX_HDR_SIZE) ) */
3648 + if ((framelen == -1) && ((tbuf_ptr - start_flag) > (TS0710_MAX_HDR_SIZE + SEQ_FIELD_SIZE))) { /*For BP UART problem */
3649 + /*short_pkt = (short_frame *) (start_flag + 1); */
3650 + short_pkt = (short_frame *) (start_flag + ADDRESS_FIELD_OFFSET); /*For BP UART problem */
3651 + if (short_pkt->h.length.ea == 1) { /* short frame */
3652 + /*framelen = TS0710_MAX_HDR_SIZE + short_pkt->h.length.len + 1; */
3653 + framelen = TS0710_MAX_HDR_SIZE + short_pkt->h.length.len + 1 + SEQ_FIELD_SIZE; /*For BP UART problem */
3654 + } else { /* long frame */
3655 + /*long_pkt = (long_frame *) (start_flag + 1); */
3656 + long_pkt = (long_frame *) (start_flag + ADDRESS_FIELD_OFFSET); /*For BP UART problem */
3657 + /*framelen = TS0710_MAX_HDR_SIZE + GET_LONG_LENGTH( long_pkt->h.length ) + 2; */
3658 + framelen = TS0710_MAX_HDR_SIZE + GET_LONG_LENGTH(long_pkt->h.length) + 2 + SEQ_FIELD_SIZE; /*For BP UART problem */
3661 + /*if( framelen > TS0710MUX_MAX_TOTAL_FRAME_SIZE ) { */
3662 + if (framelen > (TS0710MUX_MAX_TOTAL_FRAME_SIZE + SEQ_FIELD_SIZE)) { /*For BP UART problem */
3663 + TS0710_LOGSTR_FRAME(0, start_flag,
3667 + ("MUX Error: %s: frame length:%d is bigger than Max total frame size:%d\n",
3668 + /*__FUNCTION__, framelen, TS0710MUX_MAX_TOTAL_FRAME_SIZE);*/
3669 + __FUNCTION__, framelen, (TS0710MUX_MAX_TOTAL_FRAME_SIZE + SEQ_FIELD_SIZE)); /*For BP UART problem */
3670 + search = start_flag + 1;
3677 + if ((framelen != -1)
3678 + && ((tbuf_ptr - start_flag) >= framelen)) {
3679 + if (*(start_flag + framelen - 1) == TS0710_BASIC_FLAG) { /* OK, We got one frame */
3681 + /*For BP UART problem Begin */
3682 + TS0710_LOGSTR_FRAME(0, start_flag,
3684 + TS0710_DEBUGHEX(start_flag, framelen);
3687 + (short_frame *) (start_flag +
3688 + ADDRESS_FIELD_OFFSET);
3689 + if ((short_pkt->h.length.ea) == 0) {
3691 + (long_frame *) (start_flag +
3692 + ADDRESS_FIELD_OFFSET);
3694 + GET_LONG_LENGTH(long_pkt->h.
3702 + SLIDE_BP_SEQ_OFFSET),
3705 + *(uih_data_start +
3709 + short_pkt->h.length.len;
3716 + SLIDE_BP_SEQ_OFFSET),
3719 + *(uih_data_start +
3726 + SLIDE_BP_SEQ_OFFSET)) {
3728 + if (expect_seq >= 4) {
3733 + (&ts0710_connection,
3736 + FIRST_BP_SEQ_OFFSET),
3738 + SECOND_BP_SEQ_OFFSET));
3741 + (&ts0710_connection,
3746 + (&ts0710_connection,
3748 + ADDRESS_FIELD_OFFSET,
3756 + SLIDE_BP_SEQ_OFFSET)
3761 + ("MUX sequence number %d is not expected %d, discard data!\n",
3765 + SLIDE_BP_SEQ_OFFSET),
3770 + (&ts0710_connection,
3775 + FIRST_BP_SEQ_OFFSET),
3779 + SECOND_BP_SEQ_OFFSET));
3782 + (&ts0710_connection,
3792 + ("MUX bp log: %s\n",
3798 + } else { /* crc_error */
3799 + search = start_flag + 1;
3803 + } /*End if(!crc_error) */
3805 + /*For BP UART problem End */
3807 +/*For BP UART problem
3808 + TS0710_LOGSTR_FRAME(0, start_flag, framelen);
3809 + TS0710_DEBUGHEX(start_flag, framelen);
3810 + ts0710_recv_data(&ts0710_connection, start_flag + 1, framelen - 2);
3812 + search = start_flag + framelen;
3814 + TS0710_LOGSTR_FRAME(0, start_flag,
3816 + TS0710_DEBUGHEX(start_flag, framelen);
3818 + ("MUX: Lost synchronization!\n");
3819 + search = start_flag + 1;
3827 + if (start_flag != &tbuf[0]) {
3829 + from = start_flag;
3830 + count = tbuf_ptr - start_flag;
3835 + tbuf_ptr -= (start_flag - tbuf);
3836 + start_flag = tbuf;
3839 + } /* End Frame Start Flag found */
3840 + } /* End while(1) */
3842 + clear_bit(RECV_RUNNING, &mux_recv_flags);
3845 +static void post_recv_worker(void *private_)
3847 + ts0710_con *ts0710 = &ts0710_connection;
3849 + struct tty_struct *tty;
3851 + __u8 flow_control;
3853 + mux_recv_struct *recv_info, *recv_info2, *post_recv_q;
3855 + mux_recv_packet *recv_packet, *recv_packet2;
3858 + UNUSED_PARAM(private_);
3860 + if (test_and_set_bit(RECV_RUNNING, &mux_recv_flags)) {
3861 + schedule_work(&post_recv_tqueue);
3865 + TS0710_DEBUG("Enter into post_recv_worker");
3868 + if (!mux_recv_queue) {
3872 + post_recv_q = NULL;
3873 + recv_info2 = mux_recv_queue;
3874 + while ((recv_info = recv_info2)) {
3875 + recv_info2 = recv_info->next;
3877 + if (!(recv_info->total)) {
3879 + ("MUX Error: %s: Should not get here, recv_info->total == 0 \n",
3884 + tty_idx = recv_info->no_tty;
3885 + dlci = tty2dlci[tty_idx];
3886 + tty = mux_table[tty_idx];
3887 + if ((!mux_tty[tty_idx]) || (!tty)) {
3889 + ("MUX: No application waiting for, free recv_info! tty_idx:%d\n",
3891 + mux_recv_info_flags[tty_idx] = 0;
3892 + free_mux_recv_struct(mux_recv_info[tty_idx]);
3893 + mux_recv_info[tty_idx] = 0;
3894 + ts0710_flow_on(dlci, ts0710);
3898 + TS0710_DEBUG("/dev/mux%d recv_info->total is: %d", tty_idx,
3899 + recv_info->total);
3901 + if (test_bit(TTY_THROTTLED, &tty->flags)) {
3902 + add_post_recv_queue(&post_recv_q, recv_info);
3904 + } else if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
3906 + add_post_recv_queue(&post_recv_q, recv_info);
3911 + recv_packet2 = recv_info->mux_packet;
3912 + while (recv_info->total) {
3913 + recv_room = 65535;
3914 + if (tty->receive_room)
3915 + recv_room = tty->receive_room;
3917 + if (recv_info->length) {
3918 + if (recv_room < recv_info->length) {
3923 + /* Put queued data into read buffer of tty */
3925 + ("Put queued recv data into read buffer of /dev/mux%d",
3927 + TS0710_DEBUGHEX(recv_info->data,
3928 + recv_info->length);
3929 + (tty->ldisc.receive_buf) (tty, recv_info->data,
3931 + recv_info->length);
3932 + recv_info->total -= recv_info->length;
3933 + recv_info->length = 0;
3934 + } else { /* recv_info->length == 0 */
3935 + if ((recv_packet = recv_packet2)) {
3936 + recv_packet2 = recv_packet->next;
3938 + if (recv_room < recv_packet->length) {
3940 + recv_info->mux_packet =
3945 + /* Put queued data into read buffer of tty */
3947 + ("Put queued recv data into read buffer of /dev/mux%d",
3949 + TS0710_DEBUGHEX(recv_packet->data,
3950 + recv_packet->length);
3951 + (tty->ldisc.receive_buf) (tty,
3956 + recv_info->total -= recv_packet->length;
3957 + free_mux_recv_packet(recv_packet);
3960 + ("MUX Error: %s: Should not get here, recv_info->total is:%u \n",
3961 + __FUNCTION__, recv_info->total);
3963 + } /* End recv_info->length == 0 */
3964 + } /* End while( recv_info->total ) */
3966 + if (!(recv_info->total)) {
3967 + /* Important clear */
3968 + recv_info->mux_packet = 0;
3970 + if (recv_info->post_unthrottle) {
3971 + /* Do something for post_unthrottle */
3972 + ts0710_flow_on(dlci, ts0710);
3973 + recv_info->post_unthrottle = 0;
3976 + add_post_recv_queue(&post_recv_q, recv_info);
3978 + if (flow_control) {
3979 + /* Do something for flow control */
3980 + if (recv_info->post_unthrottle) {
3981 + set_bit(TTY_THROTTLED, &tty->flags);
3982 + recv_info->post_unthrottle = 0;
3984 + ts0710_flow_off(tty, dlci, ts0710);
3986 + } /* End if( flow_control ) */
3988 + } /* End while( (recv_info = recv_info2) ) */
3990 + mux_recv_queue = post_recv_q;
3993 + if (post_recv_count_flag) {
3994 + post_recv_count_flag = 0;
3995 + for (j = 0; j < TS0710MUX_COUNT_IDX_NUM; j++) {
3996 + if (mux_data_count2[j] > 0) {
3997 + if (add_count(j, mux_data_count2[j]) == 0) {
3998 + mux_data_count2[j] = 0;
4000 + post_recv_count_flag = 1;
4004 + } /* End for (j = 0; j < TS0710MUX_COUNT_IDX_NUM; j++) */
4006 + /* End if( post_recv_count_flag ) */
4008 + schedule_work(&post_recv_tqueue);
4009 + clear_bit(RECV_RUNNING, &mux_recv_flags);
4012 +/* mux sender, call from serial.c transmit_chars() */
4013 +void mux_sender(void)
4015 + mux_send_struct *send_info;
4019 + chars = mux_chars_in_serial_buffer(COMM_FOR_MUX_TTY);
4022 + TS0710_LOG("<[]\n");
4027 + idx = mux_send_info_idx;
4028 + if ((idx < NR_MUXS) && (mux_send_info_flags[idx])) {
4029 + send_info = mux_send_info[idx];
4031 + && (send_info->filled)
4032 + && (send_info->length <=
4033 + (TS0710MUX_SERIAL_BUF_SIZE - chars))) {
4040 +static void send_worker(void *private_)
4042 + ts0710_con *ts0710 = &ts0710_connection;
4044 + mux_send_struct *send_info;
4046 + struct tty_struct *tty;
4049 + UNUSED_PARAM(private_);
4051 + TS0710_DEBUG("Enter into send_worker");
4053 + mux_send_info_idx = NR_MUXS;
4055 + if (ts0710->dlci[0].state == FLOW_STOPPED) {
4056 + TS0710_DEBUG("Flow stopped on all channels\n");
4060 + for (j = 0; j < NR_MUXS; j++) {
4062 + if (!(mux_send_info_flags[j])) {
4066 + send_info = mux_send_info[j];
4071 + if (!(send_info->filled)) {
4075 + dlci = tty2dlci[j];
4076 + if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
4077 + TS0710_DEBUG("Flow stopped on channel DLCI: %d\n",
4080 + } else if (ts0710->dlci[dlci].state != CONNECTED) {
4081 + TS0710_DEBUG("DLCI %d not connected\n", dlci);
4082 + send_info->filled = 0;
4086 + chars = mux_chars_in_serial_buffer(COMM_FOR_MUX_TTY);
4087 + if (send_info->length <= (TS0710MUX_SERIAL_BUF_SIZE - chars)) {
4088 + TS0710_DEBUG("Send queued UIH for /dev/mux%d", j);
4089 + basic_write(ts0710, (__u8 *) send_info->frame,
4090 + send_info->length);
4091 + send_info->length = 0;
4092 + send_info->filled = 0;
4094 + mux_send_info_idx = j;
4097 + } /* End for() loop */
4099 + /* Queue UIH data to be transmitted */
4100 + for (j = 0; j < NR_MUXS; j++) {
4102 + if (!(mux_send_info_flags[j])) {
4106 + send_info = mux_send_info[j];
4111 + if (send_info->filled) {
4115 + /* Now queue UIH data to send_info->buf */
4117 + if (!mux_tty[j]) {
4121 + tty = mux_table[j];
4126 + dlci = tty2dlci[j];
4127 + if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
4128 + TS0710_DEBUG("Flow stopped on channel DLCI: %d\n",
4131 + } else if (ts0710->dlci[dlci].state != CONNECTED) {
4132 + TS0710_DEBUG("DLCI %d not connected\n", dlci);
4136 + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
4137 + && tty->ldisc.write_wakeup) {
4138 + (tty->ldisc.write_wakeup) (tty);
4140 + wake_up_interruptible(&tty->write_wait);
4142 +#ifdef SERIAL_HAVE_POLL_WAIT
4143 + wake_up_interruptible(&tty->poll_wait);
4146 + if (send_info->filled) {
4147 + if (j < mux_send_info_idx) {
4148 + mux_send_info_idx = j;
4151 + } /* End for() loop */
4154 +static int get_count(__u8 idx)
4158 + if (idx > TS0710MUX_COUNT_MAX_IDX) {
4159 + TS0710_PRINTK("MUX get_count: invalid idx: %d!\n", idx);
4163 + down(&mux_data_count_mutex[idx]);
4164 + ret = mux_data_count[idx];
4165 + up(&mux_data_count_mutex[idx]);
4170 +static int set_count(__u8 idx, int count)
4172 + if (idx > TS0710MUX_COUNT_MAX_IDX) {
4173 + TS0710_PRINTK("MUX set_count: invalid idx: %d!\n", idx);
4177 + TS0710_PRINTK("MUX set_count: invalid count: %d!\n", count);
4181 + down(&mux_data_count_mutex[idx]);
4182 + mux_data_count[idx] = count;
4183 + up(&mux_data_count_mutex[idx]);
4188 +static int add_count(__u8 idx, int count)
4190 + if (idx > TS0710MUX_COUNT_MAX_IDX) {
4191 + TS0710_PRINTK("MUX add_count: invalid idx: %d!\n", idx);
4195 + TS0710_PRINTK("MUX add_count: invalid count: %d!\n", count);
4199 + if (down_trylock(&mux_data_count_mutex[idx]))
4201 + mux_data_count[idx] += count;
4202 + up(&mux_data_count_mutex[idx]);
4207 +ssize_t file_proc_read(struct file * file, char *buf, size_t size,
4210 + gprs_bytes gprsData[TS0710MUX_GPRS_SESSION_MAX];
4211 + int bufLen = sizeof(gprs_bytes) * TS0710MUX_GPRS_SESSION_MAX;
4213 + UNUSED_PARAM(file);
4214 + UNUSED_PARAM(size);
4215 + UNUSED_PARAM(ppos);
4217 + gprsData[0].recvBytes = get_count(TS0710MUX_GPRS1_RECV_COUNT_IDX);
4218 + gprsData[0].sentBytes = get_count(TS0710MUX_GPRS1_SEND_COUNT_IDX);
4219 + gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].recvBytes =
4220 + get_count(TS0710MUX_GPRS2_RECV_COUNT_IDX);
4221 + gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].sentBytes =
4222 + get_count(TS0710MUX_GPRS2_SEND_COUNT_IDX);
4224 + copy_to_user(buf, gprsData, bufLen);
4229 +ssize_t file_proc_write(struct file * file, const char *buf, size_t count,
4232 + gprs_bytes gprsData[TS0710MUX_GPRS_SESSION_MAX];
4233 + int bufLen = sizeof(gprs_bytes) * TS0710MUX_GPRS_SESSION_MAX;
4235 + UNUSED_PARAM(file);
4236 + UNUSED_PARAM(count);
4237 + UNUSED_PARAM(ppos);
4239 + memset(gprsData, 0, bufLen);
4241 + copy_from_user(gprsData, buf, bufLen);
4243 + set_count(TS0710MUX_GPRS1_RECV_COUNT_IDX, gprsData[0].recvBytes);
4244 + set_count(TS0710MUX_GPRS1_SEND_COUNT_IDX, gprsData[0].sentBytes);
4245 + set_count(TS0710MUX_GPRS2_RECV_COUNT_IDX,
4246 + gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].recvBytes);
4247 + set_count(TS0710MUX_GPRS2_SEND_COUNT_IDX,
4248 + gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].sentBytes);
4253 +static void gprs_proc_init(void)
4256 + create_proc_entry("gprsbytes", S_IRUSR | S_IWUSR, NULL);
4257 + gprs_proc_file->proc_fops = &file_proc_operations;
4260 +static void gprs_proc_exit(void)
4262 + remove_proc_entry("gprsbytes", gprs_proc_file);
4265 +static int __init mux_init(void)
4269 + if (COMM_FOR_MUX_DRIVER == NULL) {
4272 + panic("please install IPC-USB first\n");
4274 + panic("please install ttyS0 first\n");
4281 + for (j = 0; j < NR_MUXS; j++) {
4282 + mux_send_info_flags[j] = 0;
4283 + mux_send_info[j] = 0;
4284 + mux_recv_info_flags[j] = 0;
4285 + mux_recv_info[j] = 0;
4287 + mux_send_info_idx = NR_MUXS;
4288 + mux_recv_queue = NULL;
4289 + mux_recv_flags = 0;
4291 + for (j = 0; j < TS0710MUX_COUNT_IDX_NUM; j++) {
4292 + mux_data_count[j] = 0;
4293 + mux_data_count2[j] = 0;
4294 + init_MUTEX(&mux_data_count_mutex[j]);
4296 + post_recv_count_flag = 0;
4298 + INIT_WORK(&send_tqueue, send_worker, NULL);
4299 + INIT_WORK(&receive_tqueue, receive_worker, NULL);
4300 + INIT_WORK(&post_recv_tqueue, post_recv_worker, NULL);
4302 + memset(&mux_driver, 0, sizeof(struct tty_driver));
4303 + memset(&mux_tty, 0, sizeof(mux_tty));
4304 + mux_driver.magic = TTY_DRIVER_MAGIC;
4305 + mux_driver.driver_name = "ts0710mux";
4306 + mux_driver.name = "ts0710mux";
4307 + mux_driver.major = TS0710MUX_MAJOR;
4308 + mux_driver.minor_start = TS0710MUX_MINOR_START;
4309 + mux_driver.num = NR_MUXS;
4310 + mux_driver.type = TTY_DRIVER_TYPE_SERIAL;
4311 + mux_driver.subtype = SERIAL_TYPE_NORMAL;
4312 + mux_driver.init_termios = tty_std_termios;
4313 + mux_driver.init_termios.c_iflag = 0;
4314 + mux_driver.init_termios.c_oflag = 0;
4315 + mux_driver.init_termios.c_cflag = B38400 | CS8 | CREAD;
4316 + mux_driver.init_termios.c_lflag = 0;
4317 + mux_driver.flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
4319 + mux_driver.ttys = mux_table;
4320 + mux_driver.termios = mux_termios;
4321 + mux_driver.termios_locked = mux_termios_locked;
4322 +// mux_driver.driver_state = mux_state;
4323 + mux_driver.other = NULL;
4325 + mux_driver.open = mux_open;
4326 + mux_driver.close = mux_close;
4327 + mux_driver.write = mux_write;
4328 + mux_driver.write_room = mux_write_room;
4329 + mux_driver.flush_buffer = mux_flush_buffer;
4330 + mux_driver.chars_in_buffer = mux_chars_in_buffer;
4331 + mux_driver.throttle = mux_throttle;
4332 + mux_driver.unthrottle = mux_unthrottle;
4333 + mux_driver.ioctl = mux_ioctl;
4334 + mux_driver.owner = THIS_MODULE;
4336 + if (tty_register_driver(&mux_driver))
4337 + panic("Couldn't register mux driver");
4339 + COMM_MUX_DISPATCHER = mux_dispatcher;
4340 + COMM_MUX_SENDER = mux_sender;
4347 +static void __exit mux_exit(void)
4351 + COMM_MUX_DISPATCHER = NULL;
4352 + COMM_MUX_SENDER = NULL;
4356 + mux_send_info_idx = NR_MUXS;
4357 + mux_recv_queue = NULL;
4358 + for (j = 0; j < NR_MUXS; j++) {
4359 + if ((mux_send_info_flags[j]) && (mux_send_info[j])) {
4360 + kfree(mux_send_info[j]);
4362 + mux_send_info_flags[j] = 0;
4363 + mux_send_info[j] = 0;
4365 + if ((mux_recv_info_flags[j]) && (mux_recv_info[j])) {
4366 + free_mux_recv_struct(mux_recv_info[j]);
4368 + mux_recv_info_flags[j] = 0;
4369 + mux_recv_info[j] = 0;
4372 + if (tty_unregister_driver(&mux_driver))
4373 + panic("Couldn't unregister mux driver");
4376 +module_init(mux_init);
4377 +module_exit(mux_exit);
4379 +MODULE_LICENSE("GPL");
4380 +MODULE_AUTHOR("Harald Welte <laforge@openezx.org>");
4381 +MODULE_DESCRIPTION("TS 07.10 Multiplexer");
4382 Index: linux-2.6.21/drivers/char/ts0710_mux.h
4383 ===================================================================
4384 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4385 +++ linux-2.6.21/drivers/char/ts0710_mux.h 2007-05-06 17:10:21.000000000 -0300
4390 + * Copyright (C) 2002 2005 Motorola
4392 + * This program is free software; you can redistribute it and/or modify
4393 + * it under the terms of the GNU General Public License as published by
4394 + * the Free Software Foundation; either version 2 of the License, or
4395 + * (at your option) any later version.
4397 + * This program is distributed in the hope that it will be useful,
4398 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4399 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4400 + * GNU General Public License for more details.
4402 + * You should have received a copy of the GNU General Public License
4403 + * along with this program; if not, write to the Free Software
4404 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4407 + * 11/18/2002 (Motorola) - Initial version
4412 +* This header file should be included by both MUX and other applications
4413 +* which access MUX device files. It gives the additional macro definitions
4414 +* shared between MUX and applications.
4417 +/* MUX DLCI(Data Link Connection Identifier) Configuration */
4420 +* 0 Control Channel
4421 +* 1 Voice Call & Network-related
4424 +* 4 Phonebook & related
4436 +/* Mapping between DLCI and MUX device files */
4438 +* File Name Minor DLCI AT Command/Data
4439 +* /dev/mux0 0 1 AT Command
4440 +* /dev/mux1 1 2 AT Command
4441 +* /dev/mux2 2 3 AT Command
4442 +* /dev/mux3 3 4 AT Command
4443 +* /dev/mux4 4 5 AT Command
4444 +* /dev/mux5 5 6 AT Command
4445 +* /dev/mux6 6 7 AT Command
4446 +* /dev/mux7 7 8 AT Command
4447 +* /dev/mux8 8 6 Data
4448 +* /dev/mux9 9 7 Data
4449 +* /dev/mux10 10 8 Data
4450 +* /dev/mux11 11 9 Data
4451 +* /dev/mux12 12 10 Data
4452 +* /dev/mux13 13 11 Data
4453 +* /dev/mux14 14 12 Data
4454 +* /dev/mux15 15 13 Data
4457 +#define MUX_CMD_FILE_VOICE_CALL "/dev/mux0"
4458 +#define MUX_CMD_FILE_SMS_MO "/dev/mux1"
4459 +#define MUX_CMD_FILE_SMS_MT "/dev/mux2"
4460 +#define MUX_CMD_FILE_PHONEBOOK "/dev/mux3"
4461 +#define MUX_CMD_FILE_MISC "/dev/mux4"
4462 +#define MUX_CMD_FILE_CSD "/dev/mux5"
4463 +#define MUX_CMD_FILE_GPRS1 "/dev/mux6"
4464 +#define MUX_CMD_FILE_GPRS2 "/dev/mux7"
4466 +#define MUX_DATA_FILE_CSD "/dev/mux8"
4467 +#define MUX_DATA_FILE_GPRS1 "/dev/mux9"
4468 +#define MUX_DATA_FILE_GPRS2 "/dev/mux10"
4469 +#define MUX_DATA_FILE_LOGGER_CMD "/dev/mux11"
4470 +#define MUX_DATA_FILE_LOGGER_DATA "/dev/mux12"
4471 +#define MUX_DATA_FILE_TEST_CMD "/dev/mux13"
4472 +#define MUX_DATA_FILE_AGPS "/dev/mux14"
4473 +#define MUX_DATA_FILE_NET_MONITOR "/dev/mux15"
4475 +#define NUM_MUX_CMD_FILES 8
4476 +#define NUM_MUX_DATA_FILES 8
4477 +#define NUM_MUX_FILES ( NUM_MUX_CMD_FILES + NUM_MUX_DATA_FILES )
4479 +/* Special ioctl() upon a MUX device file for hanging up a call */
4480 +#define TS0710MUX_IO_MSC_HANGUP 0x54F0
4482 +/* Special ioctl() upon a MUX device file for MUX loopback test */
4483 +#define TS0710MUX_IO_TEST_CMD 0x54F1
4485 +/* Special Error code might be return from write() to a MUX device file */
4486 +#define EDISCONNECTED 900 /* Logical data link is disconnected */
4488 +/* Special Error code might be return from open() to a MUX device file */
4489 +#define EREJECTED 901 /* Logical data link connection request is rejected */
4490 Index: linux-2.6.21/drivers/char/ts0710_mux_usb.c
4491 ===================================================================
4492 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4493 +++ linux-2.6.21/drivers/char/ts0710_mux_usb.c 2007-05-06 17:10:21.000000000 -0300
4496 + * linux/drivers/usb/ipcusb.c
4498 + * Implementation of a ipc driver based Intel's Bulverde USB Host
4501 + * Copyright (C) 2003-2005 Motorola
4502 + * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
4504 + * This program is free software; you can redistribute it and/or modify
4505 + * it under the terms of the GNU General Public License as published by
4506 + * the Free Software Foundation; either version 2 of the License, or
4507 + * (at your option) any later version.
4509 + * This program is distributed in the hope that it will be useful,
4510 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4511 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4512 + * GNU General Public License for more details.
4514 + * You should have received a copy of the GNU General Public License
4515 + * along with this program; if not, write to the Free Software
4516 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4518 + * 2003-Nov-03 - (Motorola) created
4519 + * 2004-Feb-20 - (Motorola) Add Power Manager codes
4520 + * 2004-Apr-14 - (Motorola) Update Suspend/Resume codes
4521 + * 2004-May-10 - (Motorola) Add unlink_urbs codes and do some updates of send
4522 + * out urb sequence
4523 + * 2006-Jun-22 - (Harald Welte) port to Linux 2.6.x
4527 +#include <linux/kernel.h>
4528 +#include <linux/module.h>
4529 +#include <linux/list.h>
4530 +#include <linux/errno.h>
4531 +#include <asm/uaccess.h>
4532 +#include <asm/hardware.h>
4533 +#include <asm/arch/hardware.h>
4534 +#include <asm/arch-pxa/pxa-regs.h>
4535 +#include <asm/arch-pxa/ezx.h>
4536 +#include <linux/slab.h>
4537 +#include <linux/miscdevice.h>
4538 +#include <linux/init.h>
4539 +#include <linux/timer.h>
4540 +#include <linux/delay.h>
4541 +#include <linux/sched.h>
4542 +#include <linux/tty.h>
4543 +#include <linux/tty_driver.h>
4544 +#include <linux/tty_flip.h>
4545 +#include <linux/circ_buf.h>
4546 +#include <linux/usb.h>
4548 +#include "ts0710_mux_usb.h"
4550 +/*Macro defined for this driver*/
4551 +#define DRIVER_VERSION "1.0alpha1"
4552 +#define DRIVER_AUTHOR "Motorola / Harald Welte <laforge@openezx.org>"
4553 +#define DRIVER_DESC "USB IPC Driver (TS07.10 lowlevel)"
4554 +#define MOTO_IPC_VID 0x22b8
4555 +#define MOTO_IPC_PID 0x3006
4556 +#define IBUF_SIZE 32 /*urb size*/
4557 +#define IPC_USB_XMIT_SIZE 1024
4558 +#define IPC_URB_SIZE 32
4559 +#define IPC_USB_WRITE_INIT 0
4560 +#define IPC_USB_WRITE_XMIT 1
4561 +#define IPC_USB_PROBE_READY 3
4562 +#define IPC_USB_PROBE_NOT_READY 4
4563 +#define DBG_MAX_BUF_SIZE 1024
4564 +#define ICL_EVENT_INTERVAL (HZ)
4567 +#define IS_EP_BULK(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
4568 +#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
4569 +#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
4570 +/*End defined macro*/
4572 +/*global values defined*/
4573 +static struct usb_driver usb_ipc_driver;
4574 +static struct timer_list ipcusb_timer;
4575 +static struct timer_list suspend_timer;
4576 +static struct timer_list wakeup_timer;
4577 +static struct tty_struct ipcusb_tty; /* the coresponding tty struct, we just use flip buffer here. */
4578 +static struct tty_driver ipcusb_tty_driver; /* the coresponding tty driver, we just use write and chars in buff here*/
4579 +struct tty_driver *usb_for_mux_driver = NULL;
4580 +struct tty_struct *usb_for_mux_tty = NULL;
4581 +void (*usb_mux_dispatcher)(struct tty_struct *tty) = NULL;
4582 +void (*usb_mux_sender)(void) = NULL;
4583 +void (*ipcusb_ap_to_bp)(unsigned char*, int) = NULL;
4584 +void (*ipcusb_bp_to_ap)(unsigned char*, int) = NULL;
4585 +EXPORT_SYMBOL(usb_for_mux_driver);
4586 +EXPORT_SYMBOL(usb_for_mux_tty);
4587 +EXPORT_SYMBOL(usb_mux_dispatcher);
4588 +EXPORT_SYMBOL(usb_mux_sender);
4589 +EXPORT_SYMBOL(ipcusb_ap_to_bp);
4590 +EXPORT_SYMBOL(ipcusb_bp_to_ap);
4591 +static int sumbit_times = 0;
4592 +static int callback_times = 0;
4593 +//static unsigned long last_jiff = 0;
4594 +extern int usbh_finished_resume;
4595 +/*end global values defined*/
4597 +MODULE_AUTHOR(DRIVER_AUTHOR);
4598 +MODULE_DESCRIPTION(DRIVER_DESC);
4599 +MODULE_LICENSE("GPL");
4602 +#define bvd_dbg(format, arg...) printk(__FILE__ ": " format "\n" , ## arg)
4604 +#define bvd_dbg(format, arg...) do {} while (0)
4607 +/* USB device context */
4609 + struct list_head list;
4614 +struct ipc_usb_data {
4615 + u_int8_t write_finished_flag;
4616 + u_int8_t write_flag,
4619 + struct usb_device *ipc_dev;
4620 + struct urb readurb_mux,
4623 + char *obuf, *ibuf;
4624 + int writesize; /* max packet size for the
4625 + output bulk endpoint *
4626 + transfer buffers */
4628 + struct circ_buf xmit; /* write cric bufffer */
4629 + struct list_head in_buf_list;
4630 + char bulk_in_ep_mux,
4632 + bulk_in_ep_dsplog;
4633 + unsigned int ifnum;
4635 + struct tasklet_struct bh,
4641 +struct ipc_usb_data *bvd_ipc;
4644 +static void bvd_dbg_hex(__u8 *buf, int len)
4646 + static unsigned char tbuf[DBG_MAX_BUF_SIZE];
4653 + for (i=0; (i < len) && (c < (DBG_MAX_BUF_SIZE - 3)); i++) {
4654 + sprintf(&tbuf[c], "%02x ",buf[i]);
4659 + printk("%s: %s\n", __FUNCTION__, tbuf);
4662 +#define bvd_dbg_hex(buf, len)
4665 +static int unlink_urbs(struct urb *urb)
4667 + unsigned long flags;
4670 + spin_lock_irqsave(&bvd_ipc->lock, flags);
4672 + retval = usb_unlink_urb(urb);
4673 + if (retval != -EINPROGRESS && retval != 0)
4674 + printk("unlink urb err, %d", retval);
4676 + spin_unlock_irqrestore(&bvd_ipc->lock, flags);
4680 +static void append_to_inbuf_list(struct urb *urb)
4682 + buf_list_t *inbuf;
4683 + int count = urb->actual_length;
4685 + inbuf = kmalloc(sizeof(buf_list_t), GFP_KERNEL);
4687 + printk("append_to_inbuf_list: (%d) out of memory!\n",
4688 + sizeof(buf_list_t));
4692 + inbuf->size = count;
4693 + inbuf->body = kmalloc(sizeof(char)*count, GFP_KERNEL);
4694 + if (!inbuf->body) {
4696 + printk("append_to_inbuf_list: (%d) out of memory!\n",
4697 + sizeof(char)*count);
4700 + memcpy(inbuf->body, (unsigned char*)urb->transfer_buffer, count);
4701 + list_add_tail(&inbuf->list, &bvd_ipc->in_buf_list);
4704 +static void ipcusb_timeout(unsigned long data)
4706 + struct tty_struct *tty = &ipcusb_tty;
4707 + struct urb *urb = (struct urb *)data;
4709 + bvd_dbg("ipcusb_timeout***");
4711 + while (!(list_empty(&bvd_ipc->in_buf_list))) {
4713 + buf_list_t *inbuf;
4714 + struct list_head *ptr = NULL;
4716 + ptr = bvd_ipc->in_buf_list.next;
4717 + inbuf = list_entry (ptr, buf_list_t, list);
4718 + count = inbuf->size;
4719 + if (tty_insert_flip_string(tty, inbuf->body, count) >= count) {
4721 + kfree(inbuf->body);
4722 + inbuf->body = NULL;
4725 + bvd_dbg("ipcusb_timeout: bvd_ipc->in_buf_list empty!");
4730 + if (usb_mux_dispatcher)
4731 + usb_mux_dispatcher(tty); /**call Liu changhui's func.**/
4733 + if (list_empty(&bvd_ipc->in_buf_list)) {
4734 + urb->actual_length = 0;
4735 + urb->dev = bvd_ipc->ipc_dev;
4736 + if (usb_submit_urb(urb, GFP_ATOMIC))
4737 + bvd_dbg("ipcusb_timeout: failed resubmitting read urb");
4738 + bvd_dbg("ipcusb_timeout: resubmited read urb");
4740 + ipcusb_timer.data = (unsigned long)urb;
4741 + mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000));
4745 +static void usb_ipc_read_bulk(struct urb *urb, struct pt_regs *regs)
4747 + buf_list_t *inbuf;
4748 + int count = urb->actual_length;
4749 + struct tty_struct *tty = &ipcusb_tty;
4751 + bvd_dbg("usb_ipc_read_bulk: begining!");
4753 + printk("nonzero read bulk status received: %d\n", urb->status);
4755 + bvd_dbg("usb_ipc_read_bulk: urb->actual_length=%d", urb->actual_length);
4756 + bvd_dbg("usb_ipc_read_bulk: urb->transfer_buffer:");
4758 + bvd_dbg_hex((unsigned char*)urb->transfer_buffer, urb->actual_length);
4760 + if (count > 0 && ((*ipcusb_bp_to_ap) != NULL))
4761 + (*ipcusb_bp_to_ap)(urb->transfer_buffer, urb->actual_length);
4763 + if (!(list_empty(&bvd_ipc->in_buf_list))) {
4766 + bvd_dbg("usb_ipc_read_bulk: some urbs in_buf_list");
4768 + bvd_ipc->suspend_flag = 1;
4769 + append_to_inbuf_list(urb); /* append the current received urb */
4771 + if(jiffies - last_jiff > ICL_EVENT_INTERVAL)
4773 + last_jiff = jiffies;
4774 + queue_apm_event(KRNL_ICL, NULL);
4779 + while (!(list_empty(&bvd_ipc->in_buf_list))) {
4780 + struct list_head* ptr = NULL;
4781 + ptr = bvd_ipc->in_buf_list.next;
4782 + inbuf = list_entry(ptr, buf_list_t, list);
4783 + count = inbuf->size;
4786 + tty_insert_flip_string(tty, inbuf->body, count);
4789 + kfree(inbuf->body);
4790 + inbuf->body = NULL;
4794 + if (usb_mux_dispatcher && need_mux)
4795 + usb_mux_dispatcher(tty); /* call Liu changhui's func. */
4797 + if (list_empty(&bvd_ipc->in_buf_list)) {
4798 + urb->actual_length = 0;
4799 + urb->dev = bvd_ipc->ipc_dev;
4800 + if (usb_submit_urb(urb, GFP_ATOMIC))
4801 + bvd_dbg("usb_ipc_read_bulk: "
4802 + "failed resubmitting read urb");
4803 + bvd_dbg("usb_ipc_read_bulk: resubmited read urb");
4805 + ipcusb_timer.data = (unsigned long)urb;
4806 + mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000));
4808 + } else if (count > 0) {
4809 + bvd_dbg("usb_ipc_read_bulk: no urbs in_buf_list");
4810 + bvd_ipc->suspend_flag = 1;
4812 + if (tty_insert_flip_string(tty, urb->transfer_buffer,
4814 + bvd_ipc->suspend_flag = 1;
4815 + append_to_inbuf_list(urb);
4816 + ipcusb_timer.data = (unsigned long)urb;
4817 + mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000));
4819 + if(jiffies - last_jiff > ICL_EVENT_INTERVAL)
4821 + last_jiff = jiffies;
4822 + queue_apm_event(KRNL_ICL, NULL);
4827 + if (usb_mux_dispatcher)
4828 + usb_mux_dispatcher(tty); /* call Liu changhui's func. */
4830 + urb->actual_length = 0;
4831 + urb->dev = bvd_ipc->ipc_dev;
4832 + if (usb_submit_urb(urb, GFP_ATOMIC))
4833 + bvd_dbg("failed resubmitting read urb");
4835 + if(jiffies - last_jiff > ICL_EVENT_INTERVAL)
4837 + last_jiff = jiffies;
4838 + queue_apm_event(KRNL_ICL, NULL);
4841 + bvd_dbg("usb_ipc_read_bulk: resubmited read urb");
4844 + bvd_dbg("usb_ipc_read_bulk: completed!!!");
4847 +static void usb_ipc_write_bulk(struct urb *urb, struct pt_regs *regs)
4850 + bvd_ipc->write_finished_flag = 1;
4852 + bvd_dbg("usb_ipc_write_bulk: begining!");
4853 + //printk("%s: write_finished_flag=%d\n", __FUNCTION__, bvd_ipc->write_finished_flag);
4856 + printk("nonzero write bulk status received: %d\n", urb->status);
4858 + if (usb_mux_sender)
4859 + usb_mux_sender(); /**call Liu changhui's func**/
4861 + //printk("usb_ipc_write_bulk: mark ipcusb_softint!\n");
4862 + tasklet_schedule(&bvd_ipc->bh);
4864 + bvd_dbg("usb_ipc_write_bulk: finished!");
4867 +static void wakeup_timeout(unsigned long data)
4869 + GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4870 + bvd_dbg("wakup_timeout: send GPIO_MCU_INT_SW signal!");
4873 +static void suspend_timeout(unsigned long data)
4875 + if (bvd_ipc->suspend_flag == 1) {
4876 + bvd_ipc->suspend_flag = 0;
4877 + mod_timer(&suspend_timer, jiffies+(5000*HZ/1000));
4878 + bvd_dbg("suspend_timeout: add the suspend timer again");
4880 + unlink_urbs(&bvd_ipc->readurb_mux);
4883 + bvd_dbg("suspend_timeout: send SUSPEND signal! UHCRHPS3=0x%x",
4888 +static void ipcusb_xmit_data(void)
4890 + int c, count = IPC_URB_SIZE;
4895 + //printk("%s: sumbit_times=%d, callback_times=%d\n", __FUNCTION__, sumbit_times, callback_times);
4896 + if (bvd_ipc->write_finished_flag == 0)
4900 + c = CIRC_CNT_TO_END(bvd_ipc->xmit.head, bvd_ipc->xmit.tail,
4901 + IPC_USB_XMIT_SIZE);
4907 + memcpy(bvd_ipc->obuf+buf_num,
4908 + bvd_ipc->xmit.buf + bvd_ipc->xmit.tail, c);
4910 + bvd_ipc->xmit.tail = ((bvd_ipc->xmit.tail + c)
4911 + & (IPC_USB_XMIT_SIZE-1));
4916 + if (buf_num == 0) {
4917 + bvd_dbg("ipcusb_xmit_data: buf_num=%d, add suspend_timer",
4919 + bvd_ipc->suspend_flag = 0;
4920 + mod_timer(&suspend_timer, jiffies+(5000*HZ/1000));
4923 + bvd_dbg("ipcusb_xmit_data: buf_num=%d", buf_num);
4924 + bvd_dbg("ipcusb_xmit_data: bvd_ipc->obuf: ");
4926 + bvd_dbg_hex((bvd_ipc->obuf)-buf_num, buf_num);
4929 + bvd_ipc->writeurb_mux.transfer_buffer_length = buf_num;
4930 + bvd_dbg("ipcusb_xmit_data: copy data to write urb finished! ");
4932 + if ((UHCRHPS3 & 0x4) == 0x4) {
4936 + /* if BP sleep, wake up BP first */
4937 + pxa_gpio_mode(GPIO_IN | 41);
4938 + if (GPIO_is_high(41)) {
4939 + if (GPIO_is_high(GPIO_MCU_INT_SW))
4940 + GPCR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4942 + GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4945 + while (GPIO_is_high(41) && (jiffies < (time+HZ)));
4947 + if (GPIO_is_high(41)) {
4948 + printk("%s: Wakeup BP timeout! BP state is %d\n",
4949 + __FUNCTION__, GPIO_is_high(41));
4951 + if (GPIO_is_high(GPIO_MCU_INT_SW))
4952 + GPCR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4954 + GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4960 + bvd_dbg("ipcusb_xmit_data: Send RESUME signal! UHCRHPS3=0x%x",
4963 + bvd_ipc->readurb_mux.actual_length = 0;
4964 + bvd_ipc->readurb_mux.dev = bvd_ipc->ipc_dev;
4965 + if (ret = usb_submit_urb(&bvd_ipc->readurb_mux, GFP_ATOMIC))
4966 + printk("ipcusb_xmit_data: usb_submit_urb(read mux bulk)"
4967 + "failed! status=%d\n", ret);
4968 + bvd_dbg("ipcusb_xmit_data: Send a IN token successfully!");
4972 + bvd_ipc->write_finished_flag = 0;
4973 + //printk("%s: clear write_finished_flag:%d\n", __FUNCTION__, bvd_ipc->write_finished_flag);
4974 + bvd_ipc->writeurb_mux.dev = bvd_ipc->ipc_dev;
4975 + if (result = usb_submit_urb(&bvd_ipc->writeurb_mux, GFP_ATOMIC))
4976 + warn("ipcusb_xmit_data: funky result! result=%d\n", result);
4978 + bvd_dbg("ipcusb_xmit_data: usb_submit_urb finished! result:%d", result);
4983 +static void usbipc_bh_func(unsigned long param)
4985 + ipcusb_xmit_data();
4988 +extern void get_halted_bit(void);
4990 +static void usbipc_bh_bp_func(unsigned long param)
4992 + if ((UHCRHPS3 & 0x4) == 0x4) {
4995 + bvd_dbg("ipcusb_softint_send_readurb: Send RESUME signal! "
4996 + "UHCRHPS3=0x%x", UHCRHPS3);
4998 + if (bvd_ipc->ipc_flag == IPC_USB_PROBE_READY) {
5001 + /*send a IN token*/
5002 + bvd_ipc->readurb_mux.dev = bvd_ipc->ipc_dev;
5003 + if (usb_submit_urb(&bvd_ipc->readurb_mux, GFP_ATOMIC)) {
5004 + bvd_dbg("ipcusb_softint_send_readurb: "
5005 + "usb_submit_urb(read mux bulk) failed!");
5007 + bvd_dbg("ipcusb_softint_send_readurb: Send a IN token successfully!");
5008 + bvd_ipc->suspend_flag = 0;
5009 + bvd_dbg("ipcusb_softint_send_readurb: add suspend_timer");
5010 + mod_timer(&suspend_timer, jiffies+(5000*HZ/1000));
5014 +static int usb_ipc_write(struct tty_struct *tty,
5015 + const unsigned char *buf, int count)
5019 + bvd_dbg("usb_ipc_write: count=%d, buf: ", count);
5020 + bvd_dbg_hex(buf, count);
5025 + if (*ipcusb_ap_to_bp != NULL)
5026 + (*ipcusb_ap_to_bp)(buf, count);
5028 + bvd_ipc->suspend_flag = 1;
5030 + if ((bvd_ipc->ipc_flag == IPC_USB_PROBE_READY) &&
5031 + (bvd_ipc->xmit.head == bvd_ipc->xmit.tail)) {
5032 + bvd_dbg("usb_ipc_write: set write_flag");
5033 + bvd_ipc->write_flag = IPC_USB_WRITE_XMIT;
5037 + c = CIRC_SPACE_TO_END(bvd_ipc->xmit.head,
5038 + bvd_ipc->xmit.tail, IPC_USB_XMIT_SIZE);
5044 + memcpy(bvd_ipc->xmit.buf + bvd_ipc->xmit.head, buf, c);
5045 + bvd_ipc->xmit.head = ((bvd_ipc->xmit.head + c)
5046 + & (IPC_USB_XMIT_SIZE-1));
5051 + bvd_dbg("usb_ipc_write: ret=%d, bvd_ipc->xmit.buf: ", ret);
5053 + bvd_dbg_hex(bvd_ipc->xmit.buf, ret);
5055 + if (bvd_ipc->write_flag == IPC_USB_WRITE_XMIT) {
5056 + bvd_ipc->write_flag = IPC_USB_WRITE_INIT;
5057 + bvd_dbg("usb_ipc_write: mark ipcusb_softint");
5058 + tasklet_schedule(&bvd_ipc->bh);
5061 + bvd_dbg("usb_ipc_write: ret=%d\n", ret);
5065 +static int usb_ipc_chars_in_buffer(struct tty_struct *tty)
5067 + return CIRC_CNT(bvd_ipc->xmit.head, bvd_ipc->xmit.tail, IPC_USB_XMIT_SIZE);
5070 +void usb_send_readurb(void)
5072 + //printk("usb_send_readurb: begining!UHCRHPS3=0x%x, usbh_finished_resume=%d\n", UHCRHPS3, usbh_finished_resume);
5074 + if (usbh_finished_resume == 0)
5077 + tasklet_schedule(&bvd_ipc->bh_bp);
5080 +static int usb_ipc_probe(struct usb_interface *intf,
5081 + const struct usb_device_id *id)
5083 + struct usb_device *usbdev = interface_to_usbdev(intf);
5084 + struct usb_config_descriptor *ipccfg;
5085 + struct usb_interface_descriptor *interface;
5086 + struct usb_endpoint_descriptor *endpoint;
5087 + int ep_cnt, readsize, writesize;
5088 + char have_bulk_in_mux, have_bulk_out_mux;
5090 + bvd_dbg("usb_ipc_probe: vendor id 0x%x, device id 0x%x",
5091 + usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
5093 + if ((usbdev->descriptor.idVendor != MOTO_IPC_VID) ||
5094 + (usbdev->descriptor.idProduct != MOTO_IPC_PID))
5097 + /* a2590c : dsplog interface is not supported by this driver */
5098 + if (intf->minor == 2) /* dsplog interface number is 2 */
5101 + bvd_dbg("usb_ipc_probe: USB dev address:%p", usbdev);
5102 + bvd_dbg("usb_ipc_probe: ifnum:%u", intf->minor);
5104 + ipccfg = &usbdev->actconfig->desc;
5105 + bvd_dbg("usb_ipc_prob: config%d", ipccfg->bConfigurationValue);
5106 + bvd_dbg("usb_ipc_prob: bNumInterfaces = %d", ipccfg->bNumInterfaces);
5108 + /* After this point we can be a little noisy about what we are trying
5109 + * to configure, hehe. */
5110 + if (usbdev->descriptor.bNumConfigurations != 1) {
5111 + info("usb_ipc_probe: Only one device configuration "
5116 + if (usbdev->config[0].desc.bNumInterfaces != 3) {
5117 + info("usb_ipc_probe: Only three device interfaces are "
5122 + interface = &intf->cur_altsetting->desc;
5123 + endpoint = &intf->cur_altsetting->endpoint[0].desc;
5124 + /* Start checking for two bulk endpoints or ... FIXME: This is a future
5125 + * enhancement...*/
5126 + bvd_dbg("usb_ipc_probe: Number of Endpoints:%d",
5127 + (int) interface->bNumEndpoints);
5128 + if (interface->bNumEndpoints != 2) {
5129 + info("usb_ipc_probe: Only two endpoints supported.");
5133 + ep_cnt = have_bulk_in_mux = have_bulk_out_mux = 0;
5135 + bvd_dbg("usb_ipc_probe: endpoint[0] is:%x",
5136 + (&endpoint[0])->bEndpointAddress);
5137 + bvd_dbg("usb_ipc_probe: endpoint[1] is:%x ",
5138 + (&endpoint[1])->bEndpointAddress);
5140 + while (ep_cnt < interface->bNumEndpoints) {
5142 + if (!have_bulk_in_mux && IS_EP_BULK_IN(endpoint[ep_cnt])) {
5143 + bvd_dbg("usb_ipc_probe: bEndpointAddress(IN) is:%x ",
5144 + (&endpoint[ep_cnt])->bEndpointAddress);
5145 + have_bulk_in_mux =
5146 + (&endpoint[ep_cnt])->bEndpointAddress;
5147 + readsize = (&endpoint[ep_cnt])->wMaxPacketSize;
5148 + bvd_dbg("usb_ipc_probe: readsize=%d", readsize);
5153 + if (!have_bulk_out_mux && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
5154 + bvd_dbg("usb_ipc_probe: bEndpointAddress(OUT) is:%x ",
5155 + (&endpoint[ep_cnt])->bEndpointAddress);
5156 + have_bulk_out_mux =
5157 + (&endpoint[ep_cnt])->bEndpointAddress;
5158 + writesize = (&endpoint[ep_cnt])->wMaxPacketSize;
5159 + bvd_dbg("usb_ipc_probe: writesize=%d", writesize);
5164 + info("usb_ipc_probe: Undetected endpoint ^_^ ");
5165 + /* Shouldn't ever get here unless we have something weird */
5169 + /* Perform a quick check to make sure that everything worked as it
5172 + switch (interface->bNumEndpoints) {
5174 + if (!have_bulk_in_mux || !have_bulk_out_mux) {
5175 + info("usb_ipc_probe: Two bulk endpoints required.");
5180 + info("usb_ipc_probe: Endpoint determination failed ^_^ ");
5184 + /* Ok, now initialize all the relevant values */
5185 + if (!(bvd_ipc->obuf = (char *)kmalloc(writesize, GFP_KERNEL))) {
5186 + err("usb_ipc_probe: Not enough memory for the output buffer.");
5190 + bvd_dbg("usb_ipc_probe: obuf address:%p", bvd_ipc->obuf);
5192 + if (!(bvd_ipc->ibuf = (char *)kmalloc(readsize, GFP_KERNEL))) {
5193 + err("usb_ipc_probe: Not enough memory for the input buffer.");
5194 + kfree(bvd_ipc->obuf);
5198 + bvd_dbg("usb_ipc_probe: ibuf address:%p", bvd_ipc->ibuf);
5200 + bvd_ipc->ipc_flag = IPC_USB_PROBE_READY;
5201 + bvd_ipc->write_finished_flag = 1;
5202 + bvd_ipc->suspend_flag = 1;
5203 + bvd_ipc->bulk_in_ep_mux= have_bulk_in_mux;
5204 + bvd_ipc->bulk_out_ep_mux= have_bulk_out_mux;
5205 + bvd_ipc->ipc_dev = usbdev;
5206 + bvd_ipc->writesize = writesize;
5207 + INIT_LIST_HEAD (&bvd_ipc->in_buf_list);
5209 + bvd_ipc->bh.func = usbipc_bh_func;
5210 + bvd_ipc->bh.data = (unsigned long) bvd_ipc;
5212 + bvd_ipc->bh_bp.func = usbipc_bh_bp_func;
5213 + bvd_ipc->bh_bp.data = (unsigned long) bvd_ipc;
5215 + /*Build a write urb*/
5216 + usb_fill_bulk_urb(&bvd_ipc->writeurb_mux, usbdev,
5217 + usb_sndbulkpipe(bvd_ipc->ipc_dev,
5218 + bvd_ipc->bulk_out_ep_mux),
5219 + bvd_ipc->obuf, writesize, usb_ipc_write_bulk,
5221 + //bvd_ipc->writeurb_mux.transfer_flags |= USB_ASYNC_UNLINK;
5223 + /*Build a read urb and send a IN token first time*/
5224 + usb_fill_bulk_urb(&bvd_ipc->readurb_mux, usbdev,
5225 + usb_rcvbulkpipe(usbdev, bvd_ipc->bulk_in_ep_mux),
5226 + bvd_ipc->ibuf, readsize, usb_ipc_read_bulk, bvd_ipc);
5227 + //bvd_ipc->readurb_mux.transfer_flags |= USB_ASYNC_UNLINK;
5229 + usb_driver_claim_interface(&usb_ipc_driver, intf, bvd_ipc);
5230 + //usb_driver_claim_interface(&usb_ipc_driver, &ipccfg->interface[1], bvd_ipc);
5232 + // a2590c: dsplog is not supported by this driver
5233 + // usb_driver_claim_interface(&usb_ipc_driver,
5234 + // &ipccfg->interface[2], bvd_ipc);
5235 + /*send a IN token first time*/
5236 + bvd_ipc->readurb_mux.dev = bvd_ipc->ipc_dev;
5237 + if (usb_submit_urb(&bvd_ipc->readurb_mux, GFP_ATOMIC))
5238 + printk("usb_ipc_prob: usb_submit_urb(read mux bulk) failed!\n");
5240 + bvd_dbg("usb_ipc_prob: Send a IN token successfully!");
5242 + if (bvd_ipc->xmit.head != bvd_ipc->xmit.tail) {
5243 + printk("usb_ipc_probe: mark ipcusb_softint!\n");
5244 + tasklet_schedule(&bvd_ipc->bh);
5247 + printk("usb_ipc_probe: completed probe!");
5248 + usb_set_intfdata(intf, &bvd_ipc);
5252 +static void usb_ipc_disconnect(struct usb_interface *intf)
5254 + //struct usb_device *usbdev = interface_to_usbdev(intf);
5255 + struct ipc_usb_data *bvd_ipc_disconnect = usb_get_intfdata(intf);
5257 + printk("usb_ipc_disconnect:*** \n");
5259 + if ((UHCRHPS3 & 0x4) == 0)
5260 + usb_unlink_urb(&bvd_ipc_disconnect->readurb_mux);
5262 + usb_unlink_urb(&bvd_ipc_disconnect->writeurb_mux);
5264 + bvd_ipc_disconnect->ipc_flag = IPC_USB_PROBE_NOT_READY;
5265 + kfree(bvd_ipc_disconnect->ibuf);
5266 + kfree(bvd_ipc_disconnect->obuf);
5268 + usb_driver_release_interface(&usb_ipc_driver,
5269 + bvd_ipc_disconnect->ipc_dev->actconfig->interface[0]);
5270 + usb_driver_release_interface(&usb_ipc_driver,
5271 + bvd_ipc_disconnect->ipc_dev->actconfig->interface[1]);
5273 + //a2590c: dsplog interface is not supported by this driver
5274 + //usb_driver_release_interface(&usb_ipc_driver, &bvd_ipc_disconnect->ipc_dev->actconfig->interface[2]);
5276 + bvd_ipc_disconnect->ipc_dev = NULL;
5278 + usb_set_intfdata(intf, NULL);
5280 + printk("usb_ipc_disconnect completed!\n");
5283 +static struct usb_device_id usb_ipc_id_table[] = {
5284 + { USB_DEVICE(MOTO_IPC_VID, MOTO_IPC_PID) },
5285 + { } /* Terminating entry */
5288 +static struct usb_driver usb_ipc_driver = {
5289 + .name = "usb ipc",
5290 + .probe = usb_ipc_probe,
5291 + .disconnect = usb_ipc_disconnect,
5292 + .id_table = usb_ipc_id_table,
5295 +static int __init usb_ipc_init(void)
5299 + bvd_dbg("init usb_ipc");
5300 + /* register driver at the USB subsystem */
5301 + result = usb_register(&usb_ipc_driver);
5303 + err ("usb ipc driver could not be registered");
5307 + /*init the related mux interface*/
5308 + if (!(bvd_ipc = kzalloc(sizeof(struct ipc_usb_data), GFP_KERNEL))) {
5309 + err("usb_ipc_init: Out of memory.");
5310 + usb_deregister(&usb_ipc_driver);
5313 + bvd_dbg("usb_ipc_init: Address of bvd_ipc:%p", bvd_ipc);
5315 + if (!(bvd_ipc->xmit.buf = kmalloc(IPC_USB_XMIT_SIZE, GFP_KERNEL))) {
5316 + err("usb_ipc_init: Not enough memory for the input buffer.");
5318 + usb_deregister(&usb_ipc_driver);
5321 + bvd_dbg("usb_ipc_init: bvd_ipc->xmit.buf address:%p",
5322 + bvd_ipc->xmit.buf);
5323 + bvd_ipc->ipc_dev = NULL;
5324 + bvd_ipc->xmit.head = bvd_ipc->xmit.tail = 0;
5325 + bvd_ipc->write_flag = IPC_USB_WRITE_INIT;
5327 + ipcusb_tty_driver.write = usb_ipc_write;
5328 + ipcusb_tty_driver.chars_in_buffer = usb_ipc_chars_in_buffer;
5330 + usb_for_mux_driver = &ipcusb_tty_driver;
5331 + usb_for_mux_tty = &ipcusb_tty;
5333 + /* init timers for ipcusb read process and usb suspend */
5334 + init_timer(&ipcusb_timer);
5335 + ipcusb_timer.function = ipcusb_timeout;
5337 + init_timer(&suspend_timer);
5338 + suspend_timer.function = suspend_timeout;
5340 + init_timer(&wakeup_timer);
5341 + wakeup_timer.function = wakeup_timeout;
5343 + info("USB Host(Bulverde) IPC driver registered.");
5344 + info(DRIVER_VERSION ":" DRIVER_DESC);
5349 +static void __exit usb_ipc_exit(void)
5351 + bvd_dbg("cleanup bvd_ipc");
5353 + kfree(bvd_ipc->xmit.buf);
5355 + usb_deregister(&usb_ipc_driver);
5357 + info("USB Host(Bulverde) IPC driver deregistered.");
5360 +module_init(usb_ipc_init);
5361 +module_exit(usb_ipc_exit);
5362 +EXPORT_SYMBOL(usb_send_readurb);
5363 Index: linux-2.6.21/drivers/char/ts0710_mux_usb.h
5364 ===================================================================
5365 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5366 +++ linux-2.6.21/drivers/char/ts0710_mux_usb.h 2007-05-06 17:10:21.000000000 -0300
5369 + * linux/drivers/usb/ipcusb.h
5371 + * Implementation of a ipc driver based Intel's Bulverde USB Host
5374 + * Copyright (C) 2003-2005 Motorola
5376 + * This program is free software; you can redistribute it and/or modify
5377 + * it under the terms of the GNU General Public License as published by
5378 + * the Free Software Foundation; either version 2 of the License, or
5379 + * (at your option) any later version.
5381 + * This program is distributed in the hope that it will be useful,
5382 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5383 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5384 + * GNU General Public License for more details.
5386 + * You should have received a copy of the GNU General Public License
5387 + * along with this program; if not, write to the Free Software
5388 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5390 + * 2003-Nov-18 - (Motorola) created
5393 +extern struct tty_driver *usb_for_mux_driver;
5394 +extern struct tty_struct *usb_for_mux_tty;
5395 +extern void (*usb_mux_dispatcher)(struct tty_struct *tty);
5396 +extern void (*usb_mux_sender)(void);