aboutsummaryrefslogtreecommitdiff
path: root/drivers/tty/smux_private.h
blob: b9a2e89720b9ebb4ac9f2fdfa64c2ed8dbf97049 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/* drivers/tty/smux_private.h
 *
 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */
#ifndef SMUX_PRIVATE_H
#define SMUX_PRIVATE_H

#define SMUX_MAX_PKT_SIZE   8192
#define SMUX_BROADCAST_LCID 0xFF

/* SMUX Protocol Characters */
#define SMUX_MAGIC          0x33FC
#define SMUX_MAGIC_WORD1    0xFC
#define SMUX_MAGIC_WORD2    0x33
#define SMUX_WAKEUP_REQ     0xFD
#define SMUX_WAKEUP_ACK     0xFE

/* Unit testing characters */
#define SMUX_UT_ECHO_REQ    0xF0
#define SMUX_UT_ECHO_ACK_OK 0xF1
#define SMUX_UT_ECHO_ACK_FAIL 0xF2

/* Maximum number of packets in retry queue */
#define SMUX_RX_RETRY_MAX_PKTS 128
#define SMUX_RX_WM_HIGH          4
#define SMUX_RX_WM_LOW           0
#define SMUX_TX_WM_LOW           2
#define SMUX_TX_WM_HIGH          4

struct tty_struct;

/**
 * Logical Channel Structure.  One instance per channel.
 *
 * Locking Hierarchy
 * Each lock has a postfix that describes the locking level.  If multiple locks
 * are required, only increasing lock hierarchy numbers may be locked which
 * ensures avoiding a deadlock.
 *
 * Locking Example
 * If state_lock_lhb1 is currently held and the TX list needs to be
 * manipulated, then tx_lock_lhb2 may be locked since it's locking hierarchy
 * is greater.  However, if tx_lock_lhb2 is held, then state_lock_lhb1 may
 * not be acquired since it would result in a deadlock.
 *
 * Note that the Line Discipline locks (*_lha) should always be acquired
 * before the logical channel locks.
 */
struct smux_lch_t {
	/* channel state */
	spinlock_t state_lock_lhb1;
	uint8_t lcid;
	unsigned local_state;
	unsigned local_mode;
	uint8_t local_tiocm;
	unsigned options;

	unsigned remote_state;
	unsigned remote_mode;
	uint8_t remote_tiocm;

	int tx_flow_control;
	int rx_flow_control_auto;
	int rx_flow_control_client;

	/* client callbacks and private data */
	void *priv;
	void (*notify)(void *priv, int event_type, const void *metadata);
	int (*get_rx_buffer)(void *priv, void **pkt_priv, void **buffer,
								int size);

	/* RX Info */
	struct list_head rx_retry_queue;
	unsigned rx_retry_queue_cnt;
	struct delayed_work rx_retry_work;

	/* TX Info */
	spinlock_t tx_lock_lhb2;
	struct list_head tx_queue;
	struct list_head tx_ready_list;
	unsigned tx_pending_data_cnt;
	unsigned notify_lwm;
};

/* Each instance of smux_lch_t */
extern struct smux_lch_t smux_lch[SMUX_NUM_LOGICAL_CHANNELS];

/* Packet header. */
struct smux_hdr_t {
	uint16_t magic;
	uint8_t flags;
	uint8_t cmd;
	uint8_t pad_len;
	uint8_t lcid;
	uint16_t payload_len;
};

/* Internal packet structure. */
struct smux_pkt_t {
	struct smux_hdr_t hdr;
	int allocated;
	unsigned char *payload;
	int free_payload;
	struct list_head list;
	void *priv;
};

/* SMUX Packet Commands */
enum {
	SMUX_CMD_DATA = 0x0,
	SMUX_CMD_OPEN_LCH = 0x1,
	SMUX_CMD_CLOSE_LCH = 0x2,
	SMUX_CMD_STATUS = 0x3,
	SMUX_CMD_PWR_CTL = 0x4,
	SMUX_CMD_DELAY = 0x5,

	SMUX_CMD_BYTE, /* for internal usage */
	SMUX_NUM_COMMANDS
};

/* Open command flags */
enum {
	SMUX_CMD_OPEN_ACK = 1 << 0,
	SMUX_CMD_OPEN_POWER_COLLAPSE = 1 << 1,
	SMUX_CMD_OPEN_REMOTE_LOOPBACK = 1 << 2,
};

/* Close command flags */
enum {
	SMUX_CMD_CLOSE_ACK = 1 << 0,
};

/* Power command flags */
enum {
	SMUX_CMD_PWR_CTL_ACK =  1 << 0,
};

/* Local logical channel states */
enum {
	SMUX_LCH_LOCAL_CLOSED,
	SMUX_LCH_LOCAL_OPENING,
	SMUX_LCH_LOCAL_OPENED,
	SMUX_LCH_LOCAL_CLOSING,
};

/* Remote logical channel states */
enum {
	SMUX_LCH_REMOTE_CLOSED,
	SMUX_LCH_REMOTE_OPENED,
};

/* Enum used to report various undefined actions */
enum {
	SMUX_UNDEF_LONG,
	SMUX_UNDEF_SHORT,
};

long msm_smux_tiocm_get_atomic(struct smux_lch_t *ch);
const char *local_lch_state(unsigned state);
const char *remote_lch_state(unsigned state);
const char *lch_mode(unsigned mode);

int smux_assert_lch_id(uint32_t lcid);
void smux_init_pkt(struct smux_pkt_t *pkt);
struct smux_pkt_t *smux_alloc_pkt(void);
int smux_alloc_pkt_payload(struct smux_pkt_t *pkt);
void smux_free_pkt(struct smux_pkt_t *pkt);
int smux_serialize(struct smux_pkt_t *pkt, char *out,
					unsigned int *out_len);

void smux_rx_state_machine(const unsigned char *data, int len, int flag);
void smuxld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
			   char *fp, int count);
bool smux_remote_is_active(void);
void smux_set_loopback_data_reply_delay(uint32_t ms);
void smux_get_wakeup_counts(int *local_cnt, int *remote_cnt);

/* testing parameters */
extern int smux_byte_loopback;
extern int smux_simulate_wakeup_delay;

#endif /* SMUX_PRIVATE_H */