diff options
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/gigaset/Kconfig | 25 | ||||
-rw-r--r-- | drivers/isdn/gigaset/Makefile | 5 | ||||
-rw-r--r-- | drivers/isdn/gigaset/asyncdata.c | 662 | ||||
-rw-r--r-- | drivers/isdn/gigaset/bas-gigaset.c | 72 | ||||
-rw-r--r-- | drivers/isdn/gigaset/capi.c | 2292 | ||||
-rw-r--r-- | drivers/isdn/gigaset/common.c | 137 | ||||
-rw-r--r-- | drivers/isdn/gigaset/dummyll.c | 68 | ||||
-rw-r--r-- | drivers/isdn/gigaset/ev-layer.c | 578 | ||||
-rw-r--r-- | drivers/isdn/gigaset/gigaset.h | 176 | ||||
-rw-r--r-- | drivers/isdn/gigaset/i4l.c | 563 | ||||
-rw-r--r-- | drivers/isdn/gigaset/interface.c | 39 | ||||
-rw-r--r-- | drivers/isdn/gigaset/isocdata.c | 186 | ||||
-rw-r--r-- | drivers/isdn/gigaset/proc.c | 2 | ||||
-rw-r--r-- | drivers/isdn/gigaset/ser-gigaset.c | 56 | ||||
-rw-r--r-- | drivers/isdn/gigaset/usb-gigaset.c | 69 | ||||
-rw-r--r-- | drivers/isdn/hardware/mISDN/speedfax.c | 1 | ||||
-rw-r--r-- | drivers/isdn/mISDN/socket.c | 5 |
17 files changed, 3734 insertions, 1202 deletions
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 18ab8652aa57..dcefedc7044a 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | menuconfig ISDN_DRV_GIGASET | 1 | menuconfig ISDN_DRV_GIGASET |
2 | tristate "Siemens Gigaset support" | 2 | tristate "Siemens Gigaset support" |
3 | depends on ISDN_I4L | ||
4 | select CRC_CCITT | 3 | select CRC_CCITT |
5 | select BITREVERSE | 4 | select BITREVERSE |
6 | help | 5 | help |
@@ -11,9 +10,33 @@ menuconfig ISDN_DRV_GIGASET | |||
11 | If you have one of these devices, say M here and for at least | 10 | If you have one of these devices, say M here and for at least |
12 | one of the connection specific parts that follow. | 11 | one of the connection specific parts that follow. |
13 | This will build a module called "gigaset". | 12 | This will build a module called "gigaset". |
13 | Note: If you build your ISDN subsystem (ISDN_CAPI or ISDN_I4L) | ||
14 | as a module, you have to build this driver as a module too, | ||
15 | otherwise the Gigaset device won't show up as an ISDN device. | ||
14 | 16 | ||
15 | if ISDN_DRV_GIGASET | 17 | if ISDN_DRV_GIGASET |
16 | 18 | ||
19 | config GIGASET_CAPI | ||
20 | bool "Gigaset CAPI support (EXPERIMENTAL)" | ||
21 | depends on EXPERIMENTAL | ||
22 | depends on ISDN_CAPI='y'||(ISDN_CAPI='m'&&ISDN_DRV_GIGASET='m') | ||
23 | default ISDN_I4L='n' | ||
24 | help | ||
25 | Build the Gigaset driver as a CAPI 2.0 driver interfacing with | ||
26 | the Kernel CAPI subsystem. To use it with the old ISDN4Linux | ||
27 | subsystem you'll have to enable the capidrv glue driver. | ||
28 | (select ISDN_CAPI_CAPIDRV.) | ||
29 | Say N to build the old native ISDN4Linux variant. | ||
30 | |||
31 | config GIGASET_I4L | ||
32 | bool | ||
33 | depends on ISDN_I4L='y'||(ISDN_I4L='m'&&ISDN_DRV_GIGASET='m') | ||
34 | default !GIGASET_CAPI | ||
35 | |||
36 | config GIGASET_DUMMYLL | ||
37 | bool | ||
38 | default !GIGASET_CAPI&&!GIGASET_I4L | ||
39 | |||
17 | config GIGASET_BASE | 40 | config GIGASET_BASE |
18 | tristate "Gigaset base station support" | 41 | tristate "Gigaset base station support" |
19 | depends on USB | 42 | depends on USB |
diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile index e9d3189f56b7..c453b72272a0 100644 --- a/drivers/isdn/gigaset/Makefile +++ b/drivers/isdn/gigaset/Makefile | |||
@@ -1,4 +1,7 @@ | |||
1 | gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o | 1 | gigaset-y := common.o interface.o proc.o ev-layer.o asyncdata.o |
2 | gigaset-$(CONFIG_GIGASET_CAPI) += capi.o | ||
3 | gigaset-$(CONFIG_GIGASET_I4L) += i4l.o | ||
4 | gigaset-$(CONFIG_GIGASET_DUMMYLL) += dummyll.o | ||
2 | usb_gigaset-y := usb-gigaset.o | 5 | usb_gigaset-y := usb-gigaset.o |
3 | ser_gigaset-y := ser-gigaset.o | 6 | ser_gigaset-y := ser-gigaset.o |
4 | bas_gigaset-y := bas-gigaset.o isocdata.o | 7 | bas_gigaset-y := bas-gigaset.o isocdata.o |
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 44a58e6f8f65..ccb2a7b7c41d 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | /* check if byte must be stuffed/escaped | 20 | /* check if byte must be stuffed/escaped |
21 | * I'm not sure which data should be encoded. | 21 | * I'm not sure which data should be encoded. |
22 | * Therefore I will go the hard way and decode every value | 22 | * Therefore I will go the hard way and encode every value |
23 | * less than 0x20, the flag sequence and the control escape char. | 23 | * less than 0x20, the flag sequence and the control escape char. |
24 | */ | 24 | */ |
25 | static inline int muststuff(unsigned char c) | 25 | static inline int muststuff(unsigned char c) |
@@ -35,303 +35,383 @@ static inline int muststuff(unsigned char c) | |||
35 | 35 | ||
36 | /* == data input =========================================================== */ | 36 | /* == data input =========================================================== */ |
37 | 37 | ||
38 | /* process a block of received bytes in command mode (modem response) | 38 | /* process a block of received bytes in command mode |
39 | * (mstate != MS_LOCKED && (inputstate & INS_command)) | ||
40 | * Append received bytes to the command response buffer and forward them | ||
41 | * line by line to the response handler. Exit whenever a mode/state change | ||
42 | * might have occurred. | ||
39 | * Return value: | 43 | * Return value: |
40 | * number of processed bytes | 44 | * number of processed bytes |
41 | */ | 45 | */ |
42 | static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, | 46 | static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf) |
43 | struct inbuf_t *inbuf) | ||
44 | { | 47 | { |
48 | unsigned char *src = inbuf->data + inbuf->head; | ||
45 | struct cardstate *cs = inbuf->cs; | 49 | struct cardstate *cs = inbuf->cs; |
46 | unsigned cbytes = cs->cbytes; | 50 | unsigned cbytes = cs->cbytes; |
47 | int inputstate = inbuf->inputstate; | 51 | unsigned procbytes = 0; |
48 | int startbytes = numbytes; | 52 | unsigned char c; |
49 | 53 | ||
50 | for (;;) { | 54 | while (procbytes < numbytes) { |
51 | cs->respdata[cbytes] = c; | 55 | c = *src++; |
52 | if (c == 10 || c == 13) { | 56 | procbytes++; |
53 | gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", | 57 | |
58 | switch (c) { | ||
59 | case '\n': | ||
60 | if (cbytes == 0 && cs->respdata[0] == '\r') { | ||
61 | /* collapse LF with preceding CR */ | ||
62 | cs->respdata[0] = 0; | ||
63 | break; | ||
64 | } | ||
65 | /* --v-- fall through --v-- */ | ||
66 | case '\r': | ||
67 | /* end of message line, pass to response handler */ | ||
68 | gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)", | ||
54 | __func__, cbytes); | 69 | __func__, cbytes); |
70 | if (cbytes >= MAX_RESP_SIZE) { | ||
71 | dev_warn(cs->dev, "response too large (%d)\n", | ||
72 | cbytes); | ||
73 | cbytes = MAX_RESP_SIZE; | ||
74 | } | ||
55 | cs->cbytes = cbytes; | 75 | cs->cbytes = cbytes; |
56 | gigaset_handle_modem_response(cs); /* can change | 76 | gigaset_handle_modem_response(cs); |
57 | cs->dle */ | ||
58 | cbytes = 0; | 77 | cbytes = 0; |
59 | 78 | ||
60 | if (cs->dle && | 79 | /* store EOL byte for CRLF collapsing */ |
61 | !(inputstate & INS_DLE_command)) { | 80 | cs->respdata[0] = c; |
62 | inputstate &= ~INS_command; | ||
63 | break; | ||
64 | } | ||
65 | } else { | ||
66 | /* advance in line buffer, checking for overflow */ | ||
67 | if (cbytes < MAX_RESP_SIZE - 1) | ||
68 | cbytes++; | ||
69 | else | ||
70 | dev_warn(cs->dev, "response too large\n"); | ||
71 | } | ||
72 | 81 | ||
73 | if (!numbytes) | 82 | /* cs->dle may have changed */ |
74 | break; | 83 | if (cs->dle && !(inbuf->inputstate & INS_DLE_command)) |
75 | c = *src++; | 84 | inbuf->inputstate &= ~INS_command; |
76 | --numbytes; | 85 | |
77 | if (c == DLE_FLAG && | 86 | /* return for reevaluating state */ |
78 | (cs->dle || inputstate & INS_DLE_command)) { | 87 | goto exit; |
79 | inputstate |= INS_DLE_char; | 88 | |
80 | break; | 89 | case DLE_FLAG: |
90 | if (inbuf->inputstate & INS_DLE_char) { | ||
91 | /* quoted DLE: clear quote flag */ | ||
92 | inbuf->inputstate &= ~INS_DLE_char; | ||
93 | } else if (cs->dle || | ||
94 | (inbuf->inputstate & INS_DLE_command)) { | ||
95 | /* DLE escape, pass up for handling */ | ||
96 | inbuf->inputstate |= INS_DLE_char; | ||
97 | goto exit; | ||
98 | } | ||
99 | /* quoted or not in DLE mode: treat as regular data */ | ||
100 | /* --v-- fall through --v-- */ | ||
101 | default: | ||
102 | /* append to line buffer if possible */ | ||
103 | if (cbytes < MAX_RESP_SIZE) | ||
104 | cs->respdata[cbytes] = c; | ||
105 | cbytes++; | ||
81 | } | 106 | } |
82 | } | 107 | } |
83 | 108 | exit: | |
84 | cs->cbytes = cbytes; | 109 | cs->cbytes = cbytes; |
85 | inbuf->inputstate = inputstate; | 110 | return procbytes; |
86 | |||
87 | return startbytes - numbytes; | ||
88 | } | 111 | } |
89 | 112 | ||
90 | /* process a block of received bytes in lock mode (tty i/f) | 113 | /* process a block of received bytes in lock mode |
114 | * All received bytes are passed unmodified to the tty i/f. | ||
91 | * Return value: | 115 | * Return value: |
92 | * number of processed bytes | 116 | * number of processed bytes |
93 | */ | 117 | */ |
94 | static inline int lock_loop(unsigned char *src, int numbytes, | 118 | static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf) |
95 | struct inbuf_t *inbuf) | ||
96 | { | 119 | { |
97 | struct cardstate *cs = inbuf->cs; | 120 | unsigned char *src = inbuf->data + inbuf->head; |
98 | |||
99 | gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", | ||
100 | numbytes, src); | ||
101 | gigaset_if_receive(cs, src, numbytes); | ||
102 | 121 | ||
122 | gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src); | ||
123 | gigaset_if_receive(inbuf->cs, src, numbytes); | ||
103 | return numbytes; | 124 | return numbytes; |
104 | } | 125 | } |
105 | 126 | ||
127 | /* set up next receive skb for data mode | ||
128 | */ | ||
129 | static void new_rcv_skb(struct bc_state *bcs) | ||
130 | { | ||
131 | struct cardstate *cs = bcs->cs; | ||
132 | unsigned short hw_hdr_len = cs->hw_hdr_len; | ||
133 | |||
134 | if (bcs->ignore) { | ||
135 | bcs->skb = NULL; | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len); | ||
140 | if (bcs->skb == NULL) { | ||
141 | dev_warn(cs->dev, "could not allocate new skb\n"); | ||
142 | return; | ||
143 | } | ||
144 | skb_reserve(bcs->skb, hw_hdr_len); | ||
145 | } | ||
146 | |||
106 | /* process a block of received bytes in HDLC data mode | 147 | /* process a block of received bytes in HDLC data mode |
148 | * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) | ||
107 | * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. | 149 | * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. |
108 | * When a frame is complete, check the FCS and pass valid frames to the LL. | 150 | * When a frame is complete, check the FCS and pass valid frames to the LL. |
109 | * If DLE is encountered, return immediately to let the caller handle it. | 151 | * If DLE is encountered, return immediately to let the caller handle it. |
110 | * Return value: | 152 | * Return value: |
111 | * number of processed bytes | 153 | * number of processed bytes |
112 | * numbytes (all bytes processed) on error --FIXME | ||
113 | */ | 154 | */ |
114 | static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, | 155 | static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) |
115 | struct inbuf_t *inbuf) | ||
116 | { | 156 | { |
117 | struct cardstate *cs = inbuf->cs; | 157 | struct cardstate *cs = inbuf->cs; |
118 | struct bc_state *bcs = inbuf->bcs; | 158 | struct bc_state *bcs = cs->bcs; |
119 | int inputstate = bcs->inputstate; | 159 | int inputstate = bcs->inputstate; |
120 | __u16 fcs = bcs->fcs; | 160 | __u16 fcs = bcs->fcs; |
121 | struct sk_buff *skb = bcs->skb; | 161 | struct sk_buff *skb = bcs->skb; |
122 | unsigned char error; | 162 | unsigned char *src = inbuf->data + inbuf->head; |
123 | struct sk_buff *compskb; | 163 | unsigned procbytes = 0; |
124 | int startbytes = numbytes; | 164 | unsigned char c; |
125 | int l; | ||
126 | 165 | ||
127 | if (unlikely(inputstate & INS_byte_stuff)) { | 166 | if (inputstate & INS_byte_stuff) { |
167 | if (!numbytes) | ||
168 | return 0; | ||
128 | inputstate &= ~INS_byte_stuff; | 169 | inputstate &= ~INS_byte_stuff; |
129 | goto byte_stuff; | 170 | goto byte_stuff; |
130 | } | 171 | } |
131 | for (;;) { | 172 | |
132 | if (unlikely(c == PPP_ESCAPE)) { | 173 | while (procbytes < numbytes) { |
133 | if (unlikely(!numbytes)) { | 174 | c = *src++; |
134 | inputstate |= INS_byte_stuff; | 175 | procbytes++; |
176 | if (c == DLE_FLAG) { | ||
177 | if (inputstate & INS_DLE_char) { | ||
178 | /* quoted DLE: clear quote flag */ | ||
179 | inputstate &= ~INS_DLE_char; | ||
180 | } else if (cs->dle || (inputstate & INS_DLE_command)) { | ||
181 | /* DLE escape, pass up for handling */ | ||
182 | inputstate |= INS_DLE_char; | ||
135 | break; | 183 | break; |
136 | } | 184 | } |
137 | c = *src++; | 185 | } |
138 | --numbytes; | 186 | |
139 | if (unlikely(c == DLE_FLAG && | 187 | if (c == PPP_ESCAPE) { |
140 | (cs->dle || | 188 | /* byte stuffing indicator: pull in next byte */ |
141 | inbuf->inputstate & INS_DLE_command))) { | 189 | if (procbytes >= numbytes) { |
142 | inbuf->inputstate |= INS_DLE_char; | 190 | /* end of buffer, save for later processing */ |
143 | inputstate |= INS_byte_stuff; | 191 | inputstate |= INS_byte_stuff; |
144 | break; | 192 | break; |
145 | } | 193 | } |
146 | byte_stuff: | 194 | byte_stuff: |
195 | c = *src++; | ||
196 | procbytes++; | ||
197 | if (c == DLE_FLAG) { | ||
198 | if (inputstate & INS_DLE_char) { | ||
199 | /* quoted DLE: clear quote flag */ | ||
200 | inputstate &= ~INS_DLE_char; | ||
201 | } else if (cs->dle || | ||
202 | (inputstate & INS_DLE_command)) { | ||
203 | /* DLE escape, pass up for handling */ | ||
204 | inputstate |= | ||
205 | INS_DLE_char | INS_byte_stuff; | ||
206 | break; | ||
207 | } | ||
208 | } | ||
147 | c ^= PPP_TRANS; | 209 | c ^= PPP_TRANS; |
148 | if (unlikely(!muststuff(c))) | ||
149 | gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); | ||
150 | } else if (unlikely(c == PPP_FLAG)) { | ||
151 | if (unlikely(inputstate & INS_skip_frame)) { | ||
152 | #ifdef CONFIG_GIGASET_DEBUG | ||
153 | if (!(inputstate & INS_have_data)) { /* 7E 7E */ | ||
154 | ++bcs->emptycount; | ||
155 | } else | ||
156 | gig_dbg(DEBUG_HDLC, | ||
157 | "7e----------------------------"); | ||
158 | #endif | ||
159 | |||
160 | /* end of frame */ | ||
161 | error = 1; | ||
162 | gigaset_rcv_error(NULL, cs, bcs); | ||
163 | } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ | ||
164 | #ifdef CONFIG_GIGASET_DEBUG | 210 | #ifdef CONFIG_GIGASET_DEBUG |
165 | ++bcs->emptycount; | 211 | if (!muststuff(c)) |
212 | gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); | ||
166 | #endif | 213 | #endif |
167 | break; | 214 | } else if (c == PPP_FLAG) { |
168 | } else { | 215 | /* end of frame: process content if any */ |
216 | if (inputstate & INS_have_data) { | ||
169 | gig_dbg(DEBUG_HDLC, | 217 | gig_dbg(DEBUG_HDLC, |
170 | "7e----------------------------"); | 218 | "7e----------------------------"); |
171 | 219 | ||
172 | /* end of frame */ | 220 | /* check and pass received frame */ |
173 | error = 0; | 221 | if (!skb) { |
174 | 222 | /* skipped frame */ | |
175 | if (unlikely(fcs != PPP_GOODFCS)) { | 223 | gigaset_isdn_rcv_err(bcs); |
224 | } else if (skb->len < 2) { | ||
225 | /* frame too short for FCS */ | ||
226 | dev_warn(cs->dev, | ||
227 | "short frame (%d)\n", | ||
228 | skb->len); | ||
229 | gigaset_isdn_rcv_err(bcs); | ||
230 | dev_kfree_skb_any(skb); | ||
231 | } else if (fcs != PPP_GOODFCS) { | ||
232 | /* frame check error */ | ||
176 | dev_err(cs->dev, | 233 | dev_err(cs->dev, |
177 | "Checksum failed, %u bytes corrupted!\n", | 234 | "Checksum failed, %u bytes corrupted!\n", |
178 | skb->len); | 235 | skb->len); |
179 | compskb = NULL; | 236 | gigaset_isdn_rcv_err(bcs); |
180 | gigaset_rcv_error(compskb, cs, bcs); | 237 | dev_kfree_skb_any(skb); |
181 | error = 1; | ||
182 | } else { | 238 | } else { |
183 | if (likely((l = skb->len) > 2)) { | 239 | /* good frame */ |
184 | skb->tail -= 2; | 240 | __skb_trim(skb, skb->len - 2); |
185 | skb->len -= 2; | 241 | gigaset_skb_rcvd(bcs, skb); |
186 | } else { | ||
187 | dev_kfree_skb(skb); | ||
188 | skb = NULL; | ||
189 | inputstate |= INS_skip_frame; | ||
190 | if (l == 1) { | ||
191 | dev_err(cs->dev, | ||
192 | "invalid packet size (1)!\n"); | ||
193 | error = 1; | ||
194 | gigaset_rcv_error(NULL, | ||
195 | cs, bcs); | ||
196 | } | ||
197 | } | ||
198 | if (likely(!(error || | ||
199 | (inputstate & | ||
200 | INS_skip_frame)))) { | ||
201 | gigaset_rcv_skb(skb, cs, bcs); | ||
202 | } | ||
203 | } | 242 | } |
204 | } | ||
205 | 243 | ||
206 | if (unlikely(error)) | 244 | /* prepare reception of next frame */ |
207 | if (skb) | 245 | inputstate &= ~INS_have_data; |
208 | dev_kfree_skb(skb); | 246 | new_rcv_skb(bcs); |
209 | 247 | skb = bcs->skb; | |
210 | fcs = PPP_INITFCS; | ||
211 | inputstate &= ~(INS_have_data | INS_skip_frame); | ||
212 | if (unlikely(bcs->ignore)) { | ||
213 | inputstate |= INS_skip_frame; | ||
214 | skb = NULL; | ||
215 | } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) { | ||
216 | skb_reserve(skb, HW_HDR_LEN); | ||
217 | } else { | 248 | } else { |
218 | dev_warn(cs->dev, | 249 | /* empty frame (7E 7E) */ |
219 | "could not allocate new skb\n"); | 250 | #ifdef CONFIG_GIGASET_DEBUG |
220 | inputstate |= INS_skip_frame; | 251 | ++bcs->emptycount; |
252 | #endif | ||
253 | if (!skb) { | ||
254 | /* skipped (?) */ | ||
255 | gigaset_isdn_rcv_err(bcs); | ||
256 | new_rcv_skb(bcs); | ||
257 | skb = bcs->skb; | ||
258 | } | ||
221 | } | 259 | } |
222 | 260 | ||
223 | break; | 261 | fcs = PPP_INITFCS; |
224 | } else if (unlikely(muststuff(c))) { | 262 | continue; |
263 | #ifdef CONFIG_GIGASET_DEBUG | ||
264 | } else if (muststuff(c)) { | ||
225 | /* Should not happen. Possible after ZDLE=1<CR><LF>. */ | 265 | /* Should not happen. Possible after ZDLE=1<CR><LF>. */ |
226 | gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); | 266 | gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); |
267 | #endif | ||
227 | } | 268 | } |
228 | 269 | ||
229 | /* add character */ | 270 | /* regular data byte, append to skb */ |
230 | |||
231 | #ifdef CONFIG_GIGASET_DEBUG | 271 | #ifdef CONFIG_GIGASET_DEBUG |
232 | if (unlikely(!(inputstate & INS_have_data))) { | 272 | if (!(inputstate & INS_have_data)) { |
233 | gig_dbg(DEBUG_HDLC, "7e (%d x) ================", | 273 | gig_dbg(DEBUG_HDLC, "7e (%d x) ================", |
234 | bcs->emptycount); | 274 | bcs->emptycount); |
235 | bcs->emptycount = 0; | 275 | bcs->emptycount = 0; |
236 | } | 276 | } |
237 | #endif | 277 | #endif |
238 | |||
239 | inputstate |= INS_have_data; | 278 | inputstate |= INS_have_data; |
240 | 279 | if (skb) { | |
241 | if (likely(!(inputstate & INS_skip_frame))) { | 280 | if (skb->len == SBUFSIZE) { |
242 | if (unlikely(skb->len == SBUFSIZE)) { | ||
243 | dev_warn(cs->dev, "received packet too long\n"); | 281 | dev_warn(cs->dev, "received packet too long\n"); |
244 | dev_kfree_skb_any(skb); | 282 | dev_kfree_skb_any(skb); |
245 | skb = NULL; | 283 | /* skip remainder of packet */ |
246 | inputstate |= INS_skip_frame; | 284 | bcs->skb = skb = NULL; |
247 | break; | 285 | } else { |
286 | *__skb_put(skb, 1) = c; | ||
287 | fcs = crc_ccitt_byte(fcs, c); | ||
248 | } | 288 | } |
249 | *__skb_put(skb, 1) = c; | ||
250 | fcs = crc_ccitt_byte(fcs, c); | ||
251 | } | ||
252 | |||
253 | if (unlikely(!numbytes)) | ||
254 | break; | ||
255 | c = *src++; | ||
256 | --numbytes; | ||
257 | if (unlikely(c == DLE_FLAG && | ||
258 | (cs->dle || | ||
259 | inbuf->inputstate & INS_DLE_command))) { | ||
260 | inbuf->inputstate |= INS_DLE_char; | ||
261 | break; | ||
262 | } | 289 | } |
263 | } | 290 | } |
291 | |||
264 | bcs->inputstate = inputstate; | 292 | bcs->inputstate = inputstate; |
265 | bcs->fcs = fcs; | 293 | bcs->fcs = fcs; |
266 | bcs->skb = skb; | 294 | return procbytes; |
267 | return startbytes - numbytes; | ||
268 | } | 295 | } |
269 | 296 | ||
270 | /* process a block of received bytes in transparent data mode | 297 | /* process a block of received bytes in transparent data mode |
298 | * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC) | ||
271 | * Invert bytes, undoing byte stuffing and watching for DLE escapes. | 299 | * Invert bytes, undoing byte stuffing and watching for DLE escapes. |
272 | * If DLE is encountered, return immediately to let the caller handle it. | 300 | * If DLE is encountered, return immediately to let the caller handle it. |
273 | * Return value: | 301 | * Return value: |
274 | * number of processed bytes | 302 | * number of processed bytes |
275 | * numbytes (all bytes processed) on error --FIXME | ||
276 | */ | 303 | */ |
277 | static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, | 304 | static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) |
278 | struct inbuf_t *inbuf) | ||
279 | { | 305 | { |
280 | struct cardstate *cs = inbuf->cs; | 306 | struct cardstate *cs = inbuf->cs; |
281 | struct bc_state *bcs = inbuf->bcs; | 307 | struct bc_state *bcs = cs->bcs; |
282 | int inputstate = bcs->inputstate; | 308 | int inputstate = bcs->inputstate; |
283 | struct sk_buff *skb = bcs->skb; | 309 | struct sk_buff *skb = bcs->skb; |
284 | int startbytes = numbytes; | 310 | unsigned char *src = inbuf->data + inbuf->head; |
311 | unsigned procbytes = 0; | ||
312 | unsigned char c; | ||
285 | 313 | ||
286 | for (;;) { | 314 | if (!skb) { |
287 | /* add character */ | 315 | /* skip this block */ |
288 | inputstate |= INS_have_data; | 316 | new_rcv_skb(bcs); |
317 | return numbytes; | ||
318 | } | ||
289 | 319 | ||
290 | if (likely(!(inputstate & INS_skip_frame))) { | 320 | while (procbytes < numbytes && skb->len < SBUFSIZE) { |
291 | if (unlikely(skb->len == SBUFSIZE)) { | 321 | c = *src++; |
292 | //FIXME just pass skb up and allocate a new one | 322 | procbytes++; |
293 | dev_warn(cs->dev, "received packet too long\n"); | 323 | |
294 | dev_kfree_skb_any(skb); | 324 | if (c == DLE_FLAG) { |
295 | skb = NULL; | 325 | if (inputstate & INS_DLE_char) { |
296 | inputstate |= INS_skip_frame; | 326 | /* quoted DLE: clear quote flag */ |
327 | inputstate &= ~INS_DLE_char; | ||
328 | } else if (cs->dle || (inputstate & INS_DLE_command)) { | ||
329 | /* DLE escape, pass up for handling */ | ||
330 | inputstate |= INS_DLE_char; | ||
297 | break; | 331 | break; |
298 | } | 332 | } |
299 | *__skb_put(skb, 1) = bitrev8(c); | ||
300 | } | 333 | } |
301 | 334 | ||
302 | if (unlikely(!numbytes)) | 335 | /* regular data byte: append to current skb */ |
303 | break; | 336 | inputstate |= INS_have_data; |
304 | c = *src++; | 337 | *__skb_put(skb, 1) = bitrev8(c); |
305 | --numbytes; | ||
306 | if (unlikely(c == DLE_FLAG && | ||
307 | (cs->dle || | ||
308 | inbuf->inputstate & INS_DLE_command))) { | ||
309 | inbuf->inputstate |= INS_DLE_char; | ||
310 | break; | ||
311 | } | ||
312 | } | 338 | } |
313 | 339 | ||
314 | /* pass data up */ | 340 | /* pass data up */ |
315 | if (likely(inputstate & INS_have_data)) { | 341 | if (inputstate & INS_have_data) { |
316 | if (likely(!(inputstate & INS_skip_frame))) { | 342 | gigaset_skb_rcvd(bcs, skb); |
317 | gigaset_rcv_skb(skb, cs, bcs); | 343 | inputstate &= ~INS_have_data; |
318 | } | 344 | new_rcv_skb(bcs); |
319 | inputstate &= ~(INS_have_data | INS_skip_frame); | 345 | } |
320 | if (unlikely(bcs->ignore)) { | 346 | |
321 | inputstate |= INS_skip_frame; | 347 | bcs->inputstate = inputstate; |
322 | skb = NULL; | 348 | return procbytes; |
323 | } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) | 349 | } |
324 | != NULL)) { | 350 | |
325 | skb_reserve(skb, HW_HDR_LEN); | 351 | /* process DLE escapes |
352 | * Called whenever a DLE sequence might be encountered in the input stream. | ||
353 | * Either processes the entire DLE sequence or, if that isn't possible, | ||
354 | * notes the fact that an initial DLE has been received in the INS_DLE_char | ||
355 | * inputstate flag and resumes processing of the sequence on the next call. | ||
356 | */ | ||
357 | static void handle_dle(struct inbuf_t *inbuf) | ||
358 | { | ||
359 | struct cardstate *cs = inbuf->cs; | ||
360 | |||
361 | if (cs->mstate == MS_LOCKED) | ||
362 | return; /* no DLE processing in lock mode */ | ||
363 | |||
364 | if (!(inbuf->inputstate & INS_DLE_char)) { | ||
365 | /* no DLE pending */ | ||
366 | if (inbuf->data[inbuf->head] == DLE_FLAG && | ||
367 | (cs->dle || inbuf->inputstate & INS_DLE_command)) { | ||
368 | /* start of DLE sequence */ | ||
369 | inbuf->head++; | ||
370 | if (inbuf->head == inbuf->tail || | ||
371 | inbuf->head == RBUFSIZE) { | ||
372 | /* end of buffer, save for later processing */ | ||
373 | inbuf->inputstate |= INS_DLE_char; | ||
374 | return; | ||
375 | } | ||
326 | } else { | 376 | } else { |
327 | dev_warn(cs->dev, "could not allocate new skb\n"); | 377 | /* regular data byte */ |
328 | inputstate |= INS_skip_frame; | 378 | return; |
329 | } | 379 | } |
330 | } | 380 | } |
331 | 381 | ||
332 | bcs->inputstate = inputstate; | 382 | /* consume pending DLE */ |
333 | bcs->skb = skb; | 383 | inbuf->inputstate &= ~INS_DLE_char; |
334 | return startbytes - numbytes; | 384 | |
385 | switch (inbuf->data[inbuf->head]) { | ||
386 | case 'X': /* begin of event message */ | ||
387 | if (inbuf->inputstate & INS_command) | ||
388 | dev_notice(cs->dev, | ||
389 | "received <DLE>X in command mode\n"); | ||
390 | inbuf->inputstate |= INS_command | INS_DLE_command; | ||
391 | inbuf->head++; /* byte consumed */ | ||
392 | break; | ||
393 | case '.': /* end of event message */ | ||
394 | if (!(inbuf->inputstate & INS_DLE_command)) | ||
395 | dev_notice(cs->dev, | ||
396 | "received <DLE>. without <DLE>X\n"); | ||
397 | inbuf->inputstate &= ~INS_DLE_command; | ||
398 | /* return to data mode if in DLE mode */ | ||
399 | if (cs->dle) | ||
400 | inbuf->inputstate &= ~INS_command; | ||
401 | inbuf->head++; /* byte consumed */ | ||
402 | break; | ||
403 | case DLE_FLAG: /* DLE in data stream */ | ||
404 | /* mark as quoted */ | ||
405 | inbuf->inputstate |= INS_DLE_char; | ||
406 | if (!(cs->dle || inbuf->inputstate & INS_DLE_command)) | ||
407 | dev_notice(cs->dev, | ||
408 | "received <DLE><DLE> not in DLE mode\n"); | ||
409 | break; /* quoted byte left in buffer */ | ||
410 | default: | ||
411 | dev_notice(cs->dev, "received <DLE><%02x>\n", | ||
412 | inbuf->data[inbuf->head]); | ||
413 | /* quoted byte left in buffer */ | ||
414 | } | ||
335 | } | 415 | } |
336 | 416 | ||
337 | /** | 417 | /** |
@@ -345,94 +425,39 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, | |||
345 | */ | 425 | */ |
346 | void gigaset_m10x_input(struct inbuf_t *inbuf) | 426 | void gigaset_m10x_input(struct inbuf_t *inbuf) |
347 | { | 427 | { |
348 | struct cardstate *cs; | 428 | struct cardstate *cs = inbuf->cs; |
349 | unsigned tail, head, numbytes; | 429 | unsigned numbytes, procbytes; |
350 | unsigned char *src, c; | ||
351 | int procbytes; | ||
352 | |||
353 | head = inbuf->head; | ||
354 | tail = inbuf->tail; | ||
355 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); | ||
356 | |||
357 | if (head != tail) { | ||
358 | cs = inbuf->cs; | ||
359 | src = inbuf->data + head; | ||
360 | numbytes = (head > tail ? RBUFSIZE : tail) - head; | ||
361 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); | ||
362 | 430 | ||
363 | while (numbytes) { | 431 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail); |
364 | if (cs->mstate == MS_LOCKED) { | ||
365 | procbytes = lock_loop(src, numbytes, inbuf); | ||
366 | src += procbytes; | ||
367 | numbytes -= procbytes; | ||
368 | } else { | ||
369 | c = *src++; | ||
370 | --numbytes; | ||
371 | if (c == DLE_FLAG && (cs->dle || | ||
372 | inbuf->inputstate & INS_DLE_command)) { | ||
373 | if (!(inbuf->inputstate & INS_DLE_char)) { | ||
374 | inbuf->inputstate |= INS_DLE_char; | ||
375 | goto nextbyte; | ||
376 | } | ||
377 | /* <DLE> <DLE> => <DLE> in data stream */ | ||
378 | inbuf->inputstate &= ~INS_DLE_char; | ||
379 | } | ||
380 | 432 | ||
381 | if (!(inbuf->inputstate & INS_DLE_char)) { | 433 | while (inbuf->head != inbuf->tail) { |
382 | 434 | /* check for DLE escape */ | |
383 | /* FIXME use function pointers? */ | 435 | handle_dle(inbuf); |
384 | if (inbuf->inputstate & INS_command) | ||
385 | procbytes = cmd_loop(c, src, numbytes, inbuf); | ||
386 | else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC) | ||
387 | procbytes = hdlc_loop(c, src, numbytes, inbuf); | ||
388 | else | ||
389 | procbytes = iraw_loop(c, src, numbytes, inbuf); | ||
390 | |||
391 | src += procbytes; | ||
392 | numbytes -= procbytes; | ||
393 | } else { /* DLE char */ | ||
394 | inbuf->inputstate &= ~INS_DLE_char; | ||
395 | switch (c) { | ||
396 | case 'X': /*begin of command*/ | ||
397 | if (inbuf->inputstate & INS_command) | ||
398 | dev_warn(cs->dev, | ||
399 | "received <DLE> 'X' in command mode\n"); | ||
400 | inbuf->inputstate |= | ||
401 | INS_command | INS_DLE_command; | ||
402 | break; | ||
403 | case '.': /*end of command*/ | ||
404 | if (!(inbuf->inputstate & INS_command)) | ||
405 | dev_warn(cs->dev, | ||
406 | "received <DLE> '.' in hdlc mode\n"); | ||
407 | inbuf->inputstate &= cs->dle ? | ||
408 | ~(INS_DLE_command|INS_command) | ||
409 | : ~INS_DLE_command; | ||
410 | break; | ||
411 | //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */ | ||
412 | default: | ||
413 | dev_err(cs->dev, | ||
414 | "received 0x10 0x%02x!\n", | ||
415 | (int) c); | ||
416 | /* FIXME: reset driver?? */ | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | nextbyte: | ||
421 | if (!numbytes) { | ||
422 | /* end of buffer, check for wrap */ | ||
423 | if (head > tail) { | ||
424 | head = 0; | ||
425 | src = inbuf->data; | ||
426 | numbytes = tail; | ||
427 | } else { | ||
428 | head = tail; | ||
429 | break; | ||
430 | } | ||
431 | } | ||
432 | } | ||
433 | 436 | ||
434 | gig_dbg(DEBUG_INTR, "setting head to %u", head); | 437 | /* process a contiguous block of bytes */ |
435 | inbuf->head = head; | 438 | numbytes = (inbuf->head > inbuf->tail ? |
439 | RBUFSIZE : inbuf->tail) - inbuf->head; | ||
440 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); | ||
441 | /* | ||
442 | * numbytes may be 0 if handle_dle() ate the last byte. | ||
443 | * This does no harm, *_loop() will just return 0 immediately. | ||
444 | */ | ||
445 | |||
446 | if (cs->mstate == MS_LOCKED) | ||
447 | procbytes = lock_loop(numbytes, inbuf); | ||
448 | else if (inbuf->inputstate & INS_command) | ||
449 | procbytes = cmd_loop(numbytes, inbuf); | ||
450 | else if (cs->bcs->proto2 == L2_HDLC) | ||
451 | procbytes = hdlc_loop(numbytes, inbuf); | ||
452 | else | ||
453 | procbytes = iraw_loop(numbytes, inbuf); | ||
454 | inbuf->head += procbytes; | ||
455 | |||
456 | /* check for buffer wraparound */ | ||
457 | if (inbuf->head >= RBUFSIZE) | ||
458 | inbuf->head = 0; | ||
459 | |||
460 | gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head); | ||
436 | } | 461 | } |
437 | } | 462 | } |
438 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); | 463 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); |
@@ -440,16 +465,16 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input); | |||
440 | 465 | ||
441 | /* == data output ========================================================== */ | 466 | /* == data output ========================================================== */ |
442 | 467 | ||
443 | /* Encoding of a PPP packet into an octet stuffed HDLC frame | 468 | /* |
444 | * with FCS, opening and closing flags. | 469 | * Encode a data packet into an octet stuffed HDLC frame with FCS, |
470 | * opening and closing flags, preserving headroom data. | ||
445 | * parameters: | 471 | * parameters: |
446 | * skb skb containing original packet (freed upon return) | 472 | * skb skb containing original packet (freed upon return) |
447 | * head number of headroom bytes to allocate in result skb | ||
448 | * tail number of tailroom bytes to allocate in result skb | ||
449 | * Return value: | 473 | * Return value: |
450 | * pointer to newly allocated skb containing the result frame | 474 | * pointer to newly allocated skb containing the result frame |
475 | * and the original link layer header, NULL on error | ||
451 | */ | 476 | */ |
452 | static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) | 477 | static struct sk_buff *HDLC_Encode(struct sk_buff *skb) |
453 | { | 478 | { |
454 | struct sk_buff *hdlc_skb; | 479 | struct sk_buff *hdlc_skb; |
455 | __u16 fcs; | 480 | __u16 fcs; |
@@ -471,16 +496,19 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) | |||
471 | 496 | ||
472 | /* size of new buffer: original size + number of stuffing bytes | 497 | /* size of new buffer: original size + number of stuffing bytes |
473 | * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes | 498 | * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes |
499 | * + room for link layer header | ||
474 | */ | 500 | */ |
475 | hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head); | 501 | hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + skb->mac_len); |
476 | if (!hdlc_skb) { | 502 | if (!hdlc_skb) { |
477 | dev_kfree_skb(skb); | 503 | dev_kfree_skb_any(skb); |
478 | return NULL; | 504 | return NULL; |
479 | } | 505 | } |
480 | skb_reserve(hdlc_skb, head); | ||
481 | 506 | ||
482 | /* Copy acknowledge request into new skb */ | 507 | /* Copy link layer header into new skb */ |
483 | memcpy(hdlc_skb->head, skb->head, 2); | 508 | skb_reset_mac_header(hdlc_skb); |
509 | skb_reserve(hdlc_skb, skb->mac_len); | ||
510 | memcpy(skb_mac_header(hdlc_skb), skb_mac_header(skb), skb->mac_len); | ||
511 | hdlc_skb->mac_len = skb->mac_len; | ||
484 | 512 | ||
485 | /* Add flag sequence in front of everything.. */ | 513 | /* Add flag sequence in front of everything.. */ |
486 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; | 514 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; |
@@ -511,33 +539,42 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) | |||
511 | 539 | ||
512 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; | 540 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; |
513 | 541 | ||
514 | dev_kfree_skb(skb); | 542 | dev_kfree_skb_any(skb); |
515 | return hdlc_skb; | 543 | return hdlc_skb; |
516 | } | 544 | } |
517 | 545 | ||
518 | /* Encoding of a raw packet into an octet stuffed bit inverted frame | 546 | /* |
547 | * Encode a data packet into an octet stuffed raw bit inverted frame, | ||
548 | * preserving headroom data. | ||
519 | * parameters: | 549 | * parameters: |
520 | * skb skb containing original packet (freed upon return) | 550 | * skb skb containing original packet (freed upon return) |
521 | * head number of headroom bytes to allocate in result skb | ||
522 | * tail number of tailroom bytes to allocate in result skb | ||
523 | * Return value: | 551 | * Return value: |
524 | * pointer to newly allocated skb containing the result frame | 552 | * pointer to newly allocated skb containing the result frame |
553 | * and the original link layer header, NULL on error | ||
525 | */ | 554 | */ |
526 | static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | 555 | static struct sk_buff *iraw_encode(struct sk_buff *skb) |
527 | { | 556 | { |
528 | struct sk_buff *iraw_skb; | 557 | struct sk_buff *iraw_skb; |
529 | unsigned char c; | 558 | unsigned char c; |
530 | unsigned char *cp; | 559 | unsigned char *cp; |
531 | int len; | 560 | int len; |
532 | 561 | ||
533 | /* worst case: every byte must be stuffed */ | 562 | /* size of new buffer (worst case = every byte must be stuffed): |
534 | iraw_skb = dev_alloc_skb(2*skb->len + tail + head); | 563 | * 2 * original size + room for link layer header |
564 | */ | ||
565 | iraw_skb = dev_alloc_skb(2*skb->len + skb->mac_len); | ||
535 | if (!iraw_skb) { | 566 | if (!iraw_skb) { |
536 | dev_kfree_skb(skb); | 567 | dev_kfree_skb_any(skb); |
537 | return NULL; | 568 | return NULL; |
538 | } | 569 | } |
539 | skb_reserve(iraw_skb, head); | ||
540 | 570 | ||
571 | /* copy link layer header into new skb */ | ||
572 | skb_reset_mac_header(iraw_skb); | ||
573 | skb_reserve(iraw_skb, skb->mac_len); | ||
574 | memcpy(skb_mac_header(iraw_skb), skb_mac_header(skb), skb->mac_len); | ||
575 | iraw_skb->mac_len = skb->mac_len; | ||
576 | |||
577 | /* copy and stuff data */ | ||
541 | cp = skb->data; | 578 | cp = skb->data; |
542 | len = skb->len; | 579 | len = skb->len; |
543 | while (len--) { | 580 | while (len--) { |
@@ -546,7 +583,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | |||
546 | *(skb_put(iraw_skb, 1)) = c; | 583 | *(skb_put(iraw_skb, 1)) = c; |
547 | *(skb_put(iraw_skb, 1)) = c; | 584 | *(skb_put(iraw_skb, 1)) = c; |
548 | } | 585 | } |
549 | dev_kfree_skb(skb); | 586 | dev_kfree_skb_any(skb); |
550 | return iraw_skb; | 587 | return iraw_skb; |
551 | } | 588 | } |
552 | 589 | ||
@@ -555,8 +592,10 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | |||
555 | * @bcs: B channel descriptor structure. | 592 | * @bcs: B channel descriptor structure. |
556 | * @skb: data to send. | 593 | * @skb: data to send. |
557 | * | 594 | * |
558 | * Called by i4l.c to encode and queue an skb for sending, and start | 595 | * Called by LL to encode and queue an skb for sending, and start |
559 | * transmission if necessary. | 596 | * transmission if necessary. |
597 | * Once the payload data has been transmitted completely, gigaset_skb_sent() | ||
598 | * will be called with the skb's link layer header preserved. | ||
560 | * | 599 | * |
561 | * Return value: | 600 | * Return value: |
562 | * number of bytes accepted for sending (skb->len) if ok, | 601 | * number of bytes accepted for sending (skb->len) if ok, |
@@ -564,24 +603,25 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | |||
564 | */ | 603 | */ |
565 | int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) | 604 | int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) |
566 | { | 605 | { |
606 | struct cardstate *cs = bcs->cs; | ||
567 | unsigned len = skb->len; | 607 | unsigned len = skb->len; |
568 | unsigned long flags; | 608 | unsigned long flags; |
569 | 609 | ||
570 | if (bcs->proto2 == ISDN_PROTO_L2_HDLC) | 610 | if (bcs->proto2 == L2_HDLC) |
571 | skb = HDLC_Encode(skb, HW_HDR_LEN, 0); | 611 | skb = HDLC_Encode(skb); |
572 | else | 612 | else |
573 | skb = iraw_encode(skb, HW_HDR_LEN, 0); | 613 | skb = iraw_encode(skb); |
574 | if (!skb) { | 614 | if (!skb) { |
575 | dev_err(bcs->cs->dev, | 615 | dev_err(cs->dev, |
576 | "unable to allocate memory for encoding!\n"); | 616 | "unable to allocate memory for encoding!\n"); |
577 | return -ENOMEM; | 617 | return -ENOMEM; |
578 | } | 618 | } |
579 | 619 | ||
580 | skb_queue_tail(&bcs->squeue, skb); | 620 | skb_queue_tail(&bcs->squeue, skb); |
581 | spin_lock_irqsave(&bcs->cs->lock, flags); | 621 | spin_lock_irqsave(&cs->lock, flags); |
582 | if (bcs->cs->connected) | 622 | if (cs->connected) |
583 | tasklet_schedule(&bcs->cs->write_tasklet); | 623 | tasklet_schedule(&cs->write_tasklet); |
584 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 624 | spin_unlock_irqrestore(&cs->lock, flags); |
585 | 625 | ||
586 | return len; /* ok so far */ | 626 | return len; /* ok so far */ |
587 | } | 627 | } |
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 5ed1d99eb9f3..9fd19db045fb 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -57,7 +57,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); | |||
57 | #define USB_SX353_PRODUCT_ID 0x0022 | 57 | #define USB_SX353_PRODUCT_ID 0x0022 |
58 | 58 | ||
59 | /* table of devices that work with this driver */ | 59 | /* table of devices that work with this driver */ |
60 | static const struct usb_device_id gigaset_table [] = { | 60 | static const struct usb_device_id gigaset_table[] = { |
61 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, | 61 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, |
62 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, | 62 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, |
63 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, | 63 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, |
@@ -137,7 +137,7 @@ struct bas_cardstate { | |||
137 | #define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */ | 137 | #define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */ |
138 | 138 | ||
139 | 139 | ||
140 | static struct gigaset_driver *driver = NULL; | 140 | static struct gigaset_driver *driver; |
141 | 141 | ||
142 | /* usb specific object needed to register this driver with the usb subsystem */ | 142 | /* usb specific object needed to register this driver with the usb subsystem */ |
143 | static struct usb_driver gigaset_usb_driver = { | 143 | static struct usb_driver gigaset_usb_driver = { |
@@ -601,11 +601,12 @@ static int atread_submit(struct cardstate *cs, int timeout) | |||
601 | ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); | 601 | ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); |
602 | usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, | 602 | usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, |
603 | usb_rcvctrlpipe(ucs->udev, 0), | 603 | usb_rcvctrlpipe(ucs->udev, 0), |
604 | (unsigned char*) & ucs->dr_cmd_in, | 604 | (unsigned char *) &ucs->dr_cmd_in, |
605 | ucs->rcvbuf, ucs->rcvbuf_size, | 605 | ucs->rcvbuf, ucs->rcvbuf_size, |
606 | read_ctrl_callback, cs->inbuf); | 606 | read_ctrl_callback, cs->inbuf); |
607 | 607 | ||
608 | if ((ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC)) != 0) { | 608 | ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC); |
609 | if (ret != 0) { | ||
609 | update_basstate(ucs, 0, BS_ATRDPEND); | 610 | update_basstate(ucs, 0, BS_ATRDPEND); |
610 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", | 611 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", |
611 | get_usb_rcmsg(ret)); | 612 | get_usb_rcmsg(ret)); |
@@ -652,13 +653,11 @@ static void read_int_callback(struct urb *urb) | |||
652 | return; | 653 | return; |
653 | case -ENODEV: /* device removed */ | 654 | case -ENODEV: /* device removed */ |
654 | case -ESHUTDOWN: /* device shut down */ | 655 | case -ESHUTDOWN: /* device shut down */ |
655 | //FIXME use this as disconnect indicator? | ||
656 | gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); | 656 | gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); |
657 | return; | 657 | return; |
658 | default: /* severe trouble */ | 658 | default: /* severe trouble */ |
659 | dev_warn(cs->dev, "interrupt read: %s\n", | 659 | dev_warn(cs->dev, "interrupt read: %s\n", |
660 | get_usb_statmsg(status)); | 660 | get_usb_statmsg(status)); |
661 | //FIXME corrective action? resubmission always ok? | ||
662 | goto resubmit; | 661 | goto resubmit; |
663 | } | 662 | } |
664 | 663 | ||
@@ -742,7 +741,8 @@ static void read_int_callback(struct urb *urb) | |||
742 | kfree(ucs->rcvbuf); | 741 | kfree(ucs->rcvbuf); |
743 | ucs->rcvbuf_size = 0; | 742 | ucs->rcvbuf_size = 0; |
744 | } | 743 | } |
745 | if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { | 744 | ucs->rcvbuf = kmalloc(l, GFP_ATOMIC); |
745 | if (ucs->rcvbuf == NULL) { | ||
746 | spin_unlock_irqrestore(&cs->lock, flags); | 746 | spin_unlock_irqrestore(&cs->lock, flags); |
747 | dev_err(cs->dev, "out of memory receiving AT data\n"); | 747 | dev_err(cs->dev, "out of memory receiving AT data\n"); |
748 | error_reset(cs); | 748 | error_reset(cs); |
@@ -750,12 +750,12 @@ static void read_int_callback(struct urb *urb) | |||
750 | } | 750 | } |
751 | ucs->rcvbuf_size = l; | 751 | ucs->rcvbuf_size = l; |
752 | ucs->retry_cmd_in = 0; | 752 | ucs->retry_cmd_in = 0; |
753 | if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) { | 753 | rc = atread_submit(cs, BAS_TIMEOUT); |
754 | if (rc < 0) { | ||
754 | kfree(ucs->rcvbuf); | 755 | kfree(ucs->rcvbuf); |
755 | ucs->rcvbuf = NULL; | 756 | ucs->rcvbuf = NULL; |
756 | ucs->rcvbuf_size = 0; | 757 | ucs->rcvbuf_size = 0; |
757 | if (rc != -ENODEV) { | 758 | if (rc != -ENODEV) { |
758 | //FIXME corrective action? | ||
759 | spin_unlock_irqrestore(&cs->lock, flags); | 759 | spin_unlock_irqrestore(&cs->lock, flags); |
760 | error_reset(cs); | 760 | error_reset(cs); |
761 | break; | 761 | break; |
@@ -911,7 +911,7 @@ static int starturbs(struct bc_state *bcs) | |||
911 | int rc; | 911 | int rc; |
912 | 912 | ||
913 | /* initialize L2 reception */ | 913 | /* initialize L2 reception */ |
914 | if (bcs->proto2 == ISDN_PROTO_L2_HDLC) | 914 | if (bcs->proto2 == L2_HDLC) |
915 | bcs->inputstate |= INS_flag_hunt; | 915 | bcs->inputstate |= INS_flag_hunt; |
916 | 916 | ||
917 | /* submit all isochronous input URBs */ | 917 | /* submit all isochronous input URBs */ |
@@ -940,7 +940,8 @@ static int starturbs(struct bc_state *bcs) | |||
940 | } | 940 | } |
941 | 941 | ||
942 | dump_urb(DEBUG_ISO, "Initial isoc read", urb); | 942 | dump_urb(DEBUG_ISO, "Initial isoc read", urb); |
943 | if ((rc = usb_submit_urb(urb, GFP_ATOMIC)) != 0) | 943 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
944 | if (rc != 0) | ||
944 | goto error; | 945 | goto error; |
945 | } | 946 | } |
946 | 947 | ||
@@ -1045,7 +1046,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
1045 | 1046 | ||
1046 | /* compute frame length according to flow control */ | 1047 | /* compute frame length according to flow control */ |
1047 | ifd->length = BAS_NORMFRAME; | 1048 | ifd->length = BAS_NORMFRAME; |
1048 | if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) { | 1049 | corrbytes = atomic_read(&ubc->corrbytes); |
1050 | if (corrbytes != 0) { | ||
1049 | gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", | 1051 | gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", |
1050 | __func__, corrbytes); | 1052 | __func__, corrbytes); |
1051 | if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) | 1053 | if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) |
@@ -1064,7 +1066,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
1064 | "%s: buffer busy at frame %d", | 1066 | "%s: buffer busy at frame %d", |
1065 | __func__, nframe); | 1067 | __func__, nframe); |
1066 | /* tasklet will be restarted from | 1068 | /* tasklet will be restarted from |
1067 | gigaset_send_skb() */ | 1069 | gigaset_isoc_send_skb() */ |
1068 | } else { | 1070 | } else { |
1069 | dev_err(ucx->bcs->cs->dev, | 1071 | dev_err(ucx->bcs->cs->dev, |
1070 | "%s: buffer error %d at frame %d\n", | 1072 | "%s: buffer error %d at frame %d\n", |
@@ -1284,7 +1286,8 @@ static void read_iso_tasklet(unsigned long data) | |||
1284 | for (;;) { | 1286 | for (;;) { |
1285 | /* retrieve URB */ | 1287 | /* retrieve URB */ |
1286 | spin_lock_irqsave(&ubc->isoinlock, flags); | 1288 | spin_lock_irqsave(&ubc->isoinlock, flags); |
1287 | if (!(urb = ubc->isoindone)) { | 1289 | urb = ubc->isoindone; |
1290 | if (!urb) { | ||
1288 | spin_unlock_irqrestore(&ubc->isoinlock, flags); | 1291 | spin_unlock_irqrestore(&ubc->isoinlock, flags); |
1289 | return; | 1292 | return; |
1290 | } | 1293 | } |
@@ -1371,7 +1374,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1371 | "isochronous read: %d data bytes missing\n", | 1374 | "isochronous read: %d data bytes missing\n", |
1372 | totleft); | 1375 | totleft); |
1373 | 1376 | ||
1374 | error: | 1377 | error: |
1375 | /* URB processed, resubmit */ | 1378 | /* URB processed, resubmit */ |
1376 | for (frame = 0; frame < BAS_NUMFRAMES; frame++) { | 1379 | for (frame = 0; frame < BAS_NUMFRAMES; frame++) { |
1377 | urb->iso_frame_desc[frame].status = 0; | 1380 | urb->iso_frame_desc[frame].status = 0; |
@@ -1568,7 +1571,7 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1568 | ucs->dr_ctrl.wLength = 0; | 1571 | ucs->dr_ctrl.wLength = 0; |
1569 | usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, | 1572 | usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, |
1570 | usb_sndctrlpipe(ucs->udev, 0), | 1573 | usb_sndctrlpipe(ucs->udev, 0), |
1571 | (unsigned char*) &ucs->dr_ctrl, NULL, 0, | 1574 | (unsigned char *) &ucs->dr_ctrl, NULL, 0, |
1572 | write_ctrl_callback, ucs); | 1575 | write_ctrl_callback, ucs); |
1573 | ucs->retry_ctrl = 0; | 1576 | ucs->retry_ctrl = 0; |
1574 | ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC); | 1577 | ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC); |
@@ -1621,7 +1624,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1621 | return -EHOSTUNREACH; | 1624 | return -EHOSTUNREACH; |
1622 | } | 1625 | } |
1623 | 1626 | ||
1624 | if ((ret = starturbs(bcs)) < 0) { | 1627 | ret = starturbs(bcs); |
1628 | if (ret < 0) { | ||
1625 | dev_err(cs->dev, | 1629 | dev_err(cs->dev, |
1626 | "could not start isochronous I/O for channel B%d: %s\n", | 1630 | "could not start isochronous I/O for channel B%d: %s\n", |
1627 | bcs->channel + 1, | 1631 | bcs->channel + 1, |
@@ -1633,7 +1637,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1633 | } | 1637 | } |
1634 | 1638 | ||
1635 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; | 1639 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; |
1636 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { | 1640 | ret = req_submit(bcs, req, 0, BAS_TIMEOUT); |
1641 | if (ret < 0) { | ||
1637 | dev_err(cs->dev, "could not open channel B%d\n", | 1642 | dev_err(cs->dev, "could not open channel B%d\n", |
1638 | bcs->channel + 1); | 1643 | bcs->channel + 1); |
1639 | stopurbs(bcs->hw.bas); | 1644 | stopurbs(bcs->hw.bas); |
@@ -1677,7 +1682,8 @@ static int gigaset_close_bchannel(struct bc_state *bcs) | |||
1677 | 1682 | ||
1678 | /* channel running: tell device to close it */ | 1683 | /* channel running: tell device to close it */ |
1679 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; | 1684 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; |
1680 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) | 1685 | ret = req_submit(bcs, req, 0, BAS_TIMEOUT); |
1686 | if (ret < 0) | ||
1681 | dev_err(cs->dev, "closing channel B%d failed\n", | 1687 | dev_err(cs->dev, "closing channel B%d failed\n", |
1682 | bcs->channel + 1); | 1688 | bcs->channel + 1); |
1683 | 1689 | ||
@@ -1703,10 +1709,12 @@ static void complete_cb(struct cardstate *cs) | |||
1703 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, | 1709 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, |
1704 | "write_command: sent %u bytes, %u left", | 1710 | "write_command: sent %u bytes, %u left", |
1705 | cs->curlen, cs->cmdbytes); | 1711 | cs->curlen, cs->cmdbytes); |
1706 | if ((cs->cmdbuf = cb->next) != NULL) { | 1712 | if (cb->next != NULL) { |
1713 | cs->cmdbuf = cb->next; | ||
1707 | cs->cmdbuf->prev = NULL; | 1714 | cs->cmdbuf->prev = NULL; |
1708 | cs->curlen = cs->cmdbuf->len; | 1715 | cs->curlen = cs->cmdbuf->len; |
1709 | } else { | 1716 | } else { |
1717 | cs->cmdbuf = NULL; | ||
1710 | cs->lastcmdbuf = NULL; | 1718 | cs->lastcmdbuf = NULL; |
1711 | cs->curlen = 0; | 1719 | cs->curlen = 0; |
1712 | } | 1720 | } |
@@ -1833,7 +1841,7 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) | |||
1833 | ucs->dr_cmd_out.wLength = cpu_to_le16(len); | 1841 | ucs->dr_cmd_out.wLength = cpu_to_le16(len); |
1834 | usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev, | 1842 | usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev, |
1835 | usb_sndctrlpipe(ucs->udev, 0), | 1843 | usb_sndctrlpipe(ucs->udev, 0), |
1836 | (unsigned char*) &ucs->dr_cmd_out, buf, len, | 1844 | (unsigned char *) &ucs->dr_cmd_out, buf, len, |
1837 | write_command_callback, cs); | 1845 | write_command_callback, cs); |
1838 | rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC); | 1846 | rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC); |
1839 | if (unlikely(rc)) { | 1847 | if (unlikely(rc)) { |
@@ -1953,7 +1961,8 @@ static int gigaset_write_cmd(struct cardstate *cs, | |||
1953 | 1961 | ||
1954 | if (len > IF_WRITEBUF) | 1962 | if (len > IF_WRITEBUF) |
1955 | len = IF_WRITEBUF; | 1963 | len = IF_WRITEBUF; |
1956 | if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { | 1964 | cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); |
1965 | if (!cb) { | ||
1957 | dev_err(cs->dev, "%s: out of memory\n", __func__); | 1966 | dev_err(cs->dev, "%s: out of memory\n", __func__); |
1958 | rc = -ENOMEM; | 1967 | rc = -ENOMEM; |
1959 | goto notqueued; | 1968 | goto notqueued; |
@@ -2100,7 +2109,8 @@ static int gigaset_initbcshw(struct bc_state *bcs) | |||
2100 | } | 2109 | } |
2101 | ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL; | 2110 | ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL; |
2102 | ubc->numsub = 0; | 2111 | ubc->numsub = 0; |
2103 | if (!(ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL))) { | 2112 | ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL); |
2113 | if (!ubc->isooutbuf) { | ||
2104 | pr_err("out of memory\n"); | 2114 | pr_err("out of memory\n"); |
2105 | kfree(ubc); | 2115 | kfree(ubc); |
2106 | bcs->hw.bas = NULL; | 2116 | bcs->hw.bas = NULL; |
@@ -2252,7 +2262,8 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2252 | gig_dbg(DEBUG_ANY, | 2262 | gig_dbg(DEBUG_ANY, |
2253 | "%s: wrong alternate setting %d - trying to switch", | 2263 | "%s: wrong alternate setting %d - trying to switch", |
2254 | __func__, hostif->desc.bAlternateSetting); | 2264 | __func__, hostif->desc.bAlternateSetting); |
2255 | if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) { | 2265 | if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) |
2266 | < 0) { | ||
2256 | dev_warn(&udev->dev, "usb_set_interface failed, " | 2267 | dev_warn(&udev->dev, "usb_set_interface failed, " |
2257 | "device %d interface %d altsetting %d\n", | 2268 | "device %d interface %d altsetting %d\n", |
2258 | udev->devnum, hostif->desc.bInterfaceNumber, | 2269 | udev->devnum, hostif->desc.bInterfaceNumber, |
@@ -2321,14 +2332,16 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2321 | (endpoint->bEndpointAddress) & 0x0f), | 2332 | (endpoint->bEndpointAddress) & 0x0f), |
2322 | ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, | 2333 | ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, |
2323 | endpoint->bInterval); | 2334 | endpoint->bInterval); |
2324 | if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) { | 2335 | rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); |
2336 | if (rc != 0) { | ||
2325 | dev_err(cs->dev, "could not submit interrupt URB: %s\n", | 2337 | dev_err(cs->dev, "could not submit interrupt URB: %s\n", |
2326 | get_usb_rcmsg(rc)); | 2338 | get_usb_rcmsg(rc)); |
2327 | goto error; | 2339 | goto error; |
2328 | } | 2340 | } |
2329 | 2341 | ||
2330 | /* tell the device that the driver is ready */ | 2342 | /* tell the device that the driver is ready */ |
2331 | if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) | 2343 | rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0); |
2344 | if (rc != 0) | ||
2332 | goto error; | 2345 | goto error; |
2333 | 2346 | ||
2334 | /* tell common part that the device is ready */ | 2347 | /* tell common part that the device is ready */ |
@@ -2524,9 +2537,10 @@ static int __init bas_gigaset_init(void) | |||
2524 | int result; | 2537 | int result; |
2525 | 2538 | ||
2526 | /* allocate memory for our driver state and intialize it */ | 2539 | /* allocate memory for our driver state and intialize it */ |
2527 | if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 2540 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
2528 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 2541 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
2529 | &gigops, THIS_MODULE)) == NULL) | 2542 | &gigops, THIS_MODULE); |
2543 | if (driver == NULL) | ||
2530 | goto error; | 2544 | goto error; |
2531 | 2545 | ||
2532 | /* register this driver with the USB subsystem */ | 2546 | /* register this driver with the USB subsystem */ |
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c new file mode 100644 index 000000000000..3f5cd06af104 --- /dev/null +++ b/drivers/isdn/gigaset/capi.c | |||
@@ -0,0 +1,2292 @@ | |||
1 | /* | ||
2 | * Kernel CAPI interface for the Gigaset driver | ||
3 | * | ||
4 | * Copyright (c) 2009 by Tilman Schmidt <tilman@imap.cc>. | ||
5 | * | ||
6 | * ===================================================================== | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * ===================================================================== | ||
12 | */ | ||
13 | |||
14 | #include "gigaset.h" | ||
15 | #include <linux/ctype.h> | ||
16 | #include <linux/isdn/capilli.h> | ||
17 | #include <linux/isdn/capicmd.h> | ||
18 | #include <linux/isdn/capiutil.h> | ||
19 | |||
20 | /* missing from kernelcapi.h */ | ||
21 | #define CapiNcpiNotSupportedByProtocol 0x0001 | ||
22 | #define CapiFlagsNotSupportedByProtocol 0x0002 | ||
23 | #define CapiAlertAlreadySent 0x0003 | ||
24 | #define CapiFacilitySpecificFunctionNotSupported 0x3011 | ||
25 | |||
26 | /* missing from capicmd.h */ | ||
27 | #define CAPI_CONNECT_IND_BASELEN (CAPI_MSG_BASELEN+4+2+8*1) | ||
28 | #define CAPI_CONNECT_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN+4+3*1) | ||
29 | #define CAPI_CONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN+4+1) | ||
30 | #define CAPI_CONNECT_B3_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN+4+1) | ||
31 | #define CAPI_DATA_B3_REQ_LEN64 (CAPI_MSG_BASELEN+4+4+2+2+2+8) | ||
32 | #define CAPI_DATA_B3_CONF_LEN (CAPI_MSG_BASELEN+4+2+2) | ||
33 | #define CAPI_DISCONNECT_IND_LEN (CAPI_MSG_BASELEN+4+2) | ||
34 | #define CAPI_DISCONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN+4+2+1) | ||
35 | #define CAPI_FACILITY_CONF_BASELEN (CAPI_MSG_BASELEN+4+2+2+1) | ||
36 | /* most _CONF messages contain only Controller/PLCI/NCCI and Info parameters */ | ||
37 | #define CAPI_STDCONF_LEN (CAPI_MSG_BASELEN+4+2) | ||
38 | |||
39 | #define CAPI_FACILITY_HANDSET 0x0000 | ||
40 | #define CAPI_FACILITY_DTMF 0x0001 | ||
41 | #define CAPI_FACILITY_V42BIS 0x0002 | ||
42 | #define CAPI_FACILITY_SUPPSVC 0x0003 | ||
43 | #define CAPI_FACILITY_WAKEUP 0x0004 | ||
44 | #define CAPI_FACILITY_LI 0x0005 | ||
45 | |||
46 | #define CAPI_SUPPSVC_GETSUPPORTED 0x0000 | ||
47 | |||
48 | /* missing from capiutil.h */ | ||
49 | #define CAPIMSG_PLCI_PART(m) CAPIMSG_U8(m, 9) | ||
50 | #define CAPIMSG_NCCI_PART(m) CAPIMSG_U16(m, 10) | ||
51 | #define CAPIMSG_HANDLE_REQ(m) CAPIMSG_U16(m, 18) /* DATA_B3_REQ/_IND only! */ | ||
52 | #define CAPIMSG_FLAGS(m) CAPIMSG_U16(m, 20) | ||
53 | #define CAPIMSG_SETCONTROLLER(m, contr) capimsg_setu8(m, 8, contr) | ||
54 | #define CAPIMSG_SETPLCI_PART(m, plci) capimsg_setu8(m, 9, plci) | ||
55 | #define CAPIMSG_SETNCCI_PART(m, ncci) capimsg_setu16(m, 10, ncci) | ||
56 | #define CAPIMSG_SETFLAGS(m, flags) capimsg_setu16(m, 20, flags) | ||
57 | |||
58 | /* parameters with differing location in DATA_B3_CONF/_RESP: */ | ||
59 | #define CAPIMSG_SETHANDLE_CONF(m, handle) capimsg_setu16(m, 12, handle) | ||
60 | #define CAPIMSG_SETINFO_CONF(m, info) capimsg_setu16(m, 14, info) | ||
61 | |||
62 | /* Flags (DATA_B3_REQ/_IND) */ | ||
63 | #define CAPI_FLAGS_DELIVERY_CONFIRMATION 0x04 | ||
64 | #define CAPI_FLAGS_RESERVED (~0x1f) | ||
65 | |||
66 | /* buffer sizes */ | ||
67 | #define MAX_BC_OCTETS 11 | ||
68 | #define MAX_HLC_OCTETS 3 | ||
69 | #define MAX_NUMBER_DIGITS 20 | ||
70 | #define MAX_FMT_IE_LEN 20 | ||
71 | |||
72 | /* values for gigaset_capi_appl.connected */ | ||
73 | #define APCONN_NONE 0 /* inactive/listening */ | ||
74 | #define APCONN_SETUP 1 /* connecting */ | ||
75 | #define APCONN_ACTIVE 2 /* B channel up */ | ||
76 | |||
77 | /* registered application data structure */ | ||
78 | struct gigaset_capi_appl { | ||
79 | struct list_head ctrlist; | ||
80 | struct gigaset_capi_appl *bcnext; | ||
81 | u16 id; | ||
82 | u16 nextMessageNumber; | ||
83 | u32 listenInfoMask; | ||
84 | u32 listenCIPmask; | ||
85 | int connected; | ||
86 | }; | ||
87 | |||
88 | /* CAPI specific controller data structure */ | ||
89 | struct gigaset_capi_ctr { | ||
90 | struct capi_ctr ctr; | ||
91 | struct list_head appls; | ||
92 | struct sk_buff_head sendqueue; | ||
93 | atomic_t sendqlen; | ||
94 | /* two _cmsg structures possibly used concurrently: */ | ||
95 | _cmsg hcmsg; /* for message composition triggered from hardware */ | ||
96 | _cmsg acmsg; /* for dissection of messages sent from application */ | ||
97 | u8 bc_buf[MAX_BC_OCTETS+1]; | ||
98 | u8 hlc_buf[MAX_HLC_OCTETS+1]; | ||
99 | u8 cgpty_buf[MAX_NUMBER_DIGITS+3]; | ||
100 | u8 cdpty_buf[MAX_NUMBER_DIGITS+2]; | ||
101 | }; | ||
102 | |||
103 | /* CIP Value table (from CAPI 2.0 standard, ch. 6.1) */ | ||
104 | static struct { | ||
105 | u8 *bc; | ||
106 | u8 *hlc; | ||
107 | } cip2bchlc[] = { | ||
108 | [1] = { "8090A3", NULL }, | ||
109 | /* Speech (A-law) */ | ||
110 | [2] = { "8890", NULL }, | ||
111 | /* Unrestricted digital information */ | ||
112 | [3] = { "8990", NULL }, | ||
113 | /* Restricted digital information */ | ||
114 | [4] = { "9090A3", NULL }, | ||
115 | /* 3,1 kHz audio (A-law) */ | ||
116 | [5] = { "9190", NULL }, | ||
117 | /* 7 kHz audio */ | ||
118 | [6] = { "9890", NULL }, | ||
119 | /* Video */ | ||
120 | [7] = { "88C0C6E6", NULL }, | ||
121 | /* Packet mode */ | ||
122 | [8] = { "8890218F", NULL }, | ||
123 | /* 56 kbit/s rate adaptation */ | ||
124 | [9] = { "9190A5", NULL }, | ||
125 | /* Unrestricted digital information with tones/announcements */ | ||
126 | [16] = { "8090A3", "9181" }, | ||
127 | /* Telephony */ | ||
128 | [17] = { "9090A3", "9184" }, | ||
129 | /* Group 2/3 facsimile */ | ||
130 | [18] = { "8890", "91A1" }, | ||
131 | /* Group 4 facsimile Class 1 */ | ||
132 | [19] = { "8890", "91A4" }, | ||
133 | /* Teletex service basic and mixed mode | ||
134 | and Group 4 facsimile service Classes II and III */ | ||
135 | [20] = { "8890", "91A8" }, | ||
136 | /* Teletex service basic and processable mode */ | ||
137 | [21] = { "8890", "91B1" }, | ||
138 | /* Teletex service basic mode */ | ||
139 | [22] = { "8890", "91B2" }, | ||
140 | /* International interworking for Videotex */ | ||
141 | [23] = { "8890", "91B5" }, | ||
142 | /* Telex */ | ||
143 | [24] = { "8890", "91B8" }, | ||
144 | /* Message Handling Systems in accordance with X.400 */ | ||
145 | [25] = { "8890", "91C1" }, | ||
146 | /* OSI application in accordance with X.200 */ | ||
147 | [26] = { "9190A5", "9181" }, | ||
148 | /* 7 kHz telephony */ | ||
149 | [27] = { "9190A5", "916001" }, | ||
150 | /* Video telephony, first connection */ | ||
151 | [28] = { "8890", "916002" }, | ||
152 | /* Video telephony, second connection */ | ||
153 | }; | ||
154 | |||
155 | /* | ||
156 | * helper functions | ||
157 | * ================ | ||
158 | */ | ||
159 | |||
160 | /* | ||
161 | * emit unsupported parameter warning | ||
162 | */ | ||
163 | static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, | ||
164 | char *msgname, char *paramname) | ||
165 | { | ||
166 | if (param && *param) | ||
167 | dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", | ||
168 | msgname, paramname); | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * check for legal hex digit | ||
173 | */ | ||
174 | static inline int ishexdigit(char c) | ||
175 | { | ||
176 | if (c >= '0' && c <= '9') | ||
177 | return 1; | ||
178 | if (c >= 'A' && c <= 'F') | ||
179 | return 1; | ||
180 | if (c >= 'a' && c <= 'f') | ||
181 | return 1; | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * convert hex to binary | ||
187 | */ | ||
188 | static inline u8 hex2bin(char c) | ||
189 | { | ||
190 | int result = c & 0x0f; | ||
191 | if (c & 0x40) | ||
192 | result += 9; | ||
193 | return result; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * convert an IE from Gigaset hex string to ETSI binary representation | ||
198 | * including length byte | ||
199 | * return value: result length, -1 on error | ||
200 | */ | ||
201 | static int encode_ie(char *in, u8 *out, int maxlen) | ||
202 | { | ||
203 | int l = 0; | ||
204 | while (*in) { | ||
205 | if (!ishexdigit(in[0]) || !ishexdigit(in[1]) || l >= maxlen) | ||
206 | return -1; | ||
207 | out[++l] = (hex2bin(in[0]) << 4) + hex2bin(in[1]); | ||
208 | in += 2; | ||
209 | } | ||
210 | out[0] = l; | ||
211 | return l; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * convert an IE from ETSI binary representation including length byte | ||
216 | * to Gigaset hex string | ||
217 | */ | ||
218 | static void decode_ie(u8 *in, char *out) | ||
219 | { | ||
220 | int i = *in; | ||
221 | while (i-- > 0) { | ||
222 | /* ToDo: conversion to upper case necessary? */ | ||
223 | *out++ = toupper(hex_asc_hi(*++in)); | ||
224 | *out++ = toupper(hex_asc_lo(*in)); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * retrieve application data structure for an application ID | ||
230 | */ | ||
231 | static inline struct gigaset_capi_appl * | ||
232 | get_appl(struct gigaset_capi_ctr *iif, u16 appl) | ||
233 | { | ||
234 | struct gigaset_capi_appl *ap; | ||
235 | |||
236 | list_for_each_entry(ap, &iif->appls, ctrlist) | ||
237 | if (ap->id == appl) | ||
238 | return ap; | ||
239 | return NULL; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * dump CAPI message to kernel messages for debugging | ||
244 | */ | ||
245 | static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p) | ||
246 | { | ||
247 | #ifdef CONFIG_GIGASET_DEBUG | ||
248 | _cdebbuf *cdb; | ||
249 | |||
250 | if (!(gigaset_debuglevel & level)) | ||
251 | return; | ||
252 | |||
253 | cdb = capi_cmsg2str(p); | ||
254 | if (cdb) { | ||
255 | gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, cdb->buf); | ||
256 | cdebbuf_free(cdb); | ||
257 | } else { | ||
258 | gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, | ||
259 | capi_cmd2str(p->Command, p->Subcommand)); | ||
260 | } | ||
261 | #endif | ||
262 | } | ||
263 | |||
264 | static inline void dump_rawmsg(enum debuglevel level, const char *tag, | ||
265 | unsigned char *data) | ||
266 | { | ||
267 | #ifdef CONFIG_GIGASET_DEBUG | ||
268 | char *dbgline; | ||
269 | int i, l; | ||
270 | |||
271 | if (!(gigaset_debuglevel & level)) | ||
272 | return; | ||
273 | |||
274 | l = CAPIMSG_LEN(data); | ||
275 | if (l < 12) { | ||
276 | gig_dbg(level, "%s: ??? LEN=%04d", tag, l); | ||
277 | return; | ||
278 | } | ||
279 | gig_dbg(level, "%s: 0x%02x:0x%02x: ID=%03d #0x%04x LEN=%04d NCCI=0x%x", | ||
280 | tag, CAPIMSG_COMMAND(data), CAPIMSG_SUBCOMMAND(data), | ||
281 | CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, | ||
282 | CAPIMSG_CONTROL(data)); | ||
283 | l -= 12; | ||
284 | dbgline = kmalloc(3*l, GFP_ATOMIC); | ||
285 | if (!dbgline) | ||
286 | return; | ||
287 | for (i = 0; i < l; i++) { | ||
288 | dbgline[3*i] = hex_asc_hi(data[12+i]); | ||
289 | dbgline[3*i+1] = hex_asc_lo(data[12+i]); | ||
290 | dbgline[3*i+2] = ' '; | ||
291 | } | ||
292 | dbgline[3*l-1] = '\0'; | ||
293 | gig_dbg(level, " %s", dbgline); | ||
294 | kfree(dbgline); | ||
295 | if (CAPIMSG_COMMAND(data) == CAPI_DATA_B3 && | ||
296 | (CAPIMSG_SUBCOMMAND(data) == CAPI_REQ || | ||
297 | CAPIMSG_SUBCOMMAND(data) == CAPI_IND) && | ||
298 | CAPIMSG_DATALEN(data) > 0) { | ||
299 | l = CAPIMSG_DATALEN(data); | ||
300 | dbgline = kmalloc(3*l, GFP_ATOMIC); | ||
301 | if (!dbgline) | ||
302 | return; | ||
303 | data += CAPIMSG_LEN(data); | ||
304 | for (i = 0; i < l; i++) { | ||
305 | dbgline[3*i] = hex_asc_hi(data[i]); | ||
306 | dbgline[3*i+1] = hex_asc_lo(data[i]); | ||
307 | dbgline[3*i+2] = ' '; | ||
308 | } | ||
309 | dbgline[3*l-1] = '\0'; | ||
310 | gig_dbg(level, " %s", dbgline); | ||
311 | kfree(dbgline); | ||
312 | } | ||
313 | #endif | ||
314 | } | ||
315 | |||
316 | /* | ||
317 | * format CAPI IE as string | ||
318 | */ | ||
319 | |||
320 | static const char *format_ie(const char *ie) | ||
321 | { | ||
322 | static char result[3*MAX_FMT_IE_LEN]; | ||
323 | int len, count; | ||
324 | char *pout = result; | ||
325 | |||
326 | if (!ie) | ||
327 | return "NULL"; | ||
328 | |||
329 | count = len = ie[0]; | ||
330 | if (count > MAX_FMT_IE_LEN) | ||
331 | count = MAX_FMT_IE_LEN-1; | ||
332 | while (count--) { | ||
333 | *pout++ = hex_asc_hi(*++ie); | ||
334 | *pout++ = hex_asc_lo(*ie); | ||
335 | *pout++ = ' '; | ||
336 | } | ||
337 | if (len > MAX_FMT_IE_LEN) { | ||
338 | *pout++ = '.'; | ||
339 | *pout++ = '.'; | ||
340 | *pout++ = '.'; | ||
341 | } | ||
342 | *--pout = 0; | ||
343 | return result; | ||
344 | } | ||
345 | |||
346 | |||
347 | /* | ||
348 | * driver interface functions | ||
349 | * ========================== | ||
350 | */ | ||
351 | |||
352 | /** | ||
353 | * gigaset_skb_sent() - acknowledge transmission of outgoing skb | ||
354 | * @bcs: B channel descriptor structure. | ||
355 | * @skb: sent data. | ||
356 | * | ||
357 | * Called by hardware module {bas,ser,usb}_gigaset when the data in a | ||
358 | * skb has been successfully sent, for signalling completion to the LL. | ||
359 | */ | ||
360 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) | ||
361 | { | ||
362 | struct cardstate *cs = bcs->cs; | ||
363 | struct gigaset_capi_ctr *iif = cs->iif; | ||
364 | struct gigaset_capi_appl *ap = bcs->ap; | ||
365 | unsigned char *req = skb_mac_header(dskb); | ||
366 | struct sk_buff *cskb; | ||
367 | u16 flags; | ||
368 | |||
369 | /* update statistics */ | ||
370 | ++bcs->trans_up; | ||
371 | |||
372 | if (!ap) { | ||
373 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
374 | return; | ||
375 | } | ||
376 | |||
377 | /* don't send further B3 messages if disconnected */ | ||
378 | if (ap->connected < APCONN_ACTIVE) { | ||
379 | gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack"); | ||
380 | return; | ||
381 | } | ||
382 | |||
383 | /* ToDo: honor unset "delivery confirmation" bit */ | ||
384 | flags = CAPIMSG_FLAGS(req); | ||
385 | |||
386 | /* build DATA_B3_CONF message */ | ||
387 | cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); | ||
388 | if (!cskb) { | ||
389 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
390 | return; | ||
391 | } | ||
392 | /* frequent message, avoid _cmsg overhead */ | ||
393 | CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN); | ||
394 | CAPIMSG_SETAPPID(cskb->data, ap->id); | ||
395 | CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3); | ||
396 | CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF); | ||
397 | CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req)); | ||
398 | CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr); | ||
399 | CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1); | ||
400 | CAPIMSG_SETNCCI_PART(cskb->data, 1); | ||
401 | CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req)); | ||
402 | if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) | ||
403 | CAPIMSG_SETINFO_CONF(cskb->data, | ||
404 | CapiFlagsNotSupportedByProtocol); | ||
405 | else | ||
406 | CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR); | ||
407 | |||
408 | /* emit message */ | ||
409 | dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data); | ||
410 | capi_ctr_handle_message(&iif->ctr, ap->id, cskb); | ||
411 | } | ||
412 | EXPORT_SYMBOL_GPL(gigaset_skb_sent); | ||
413 | |||
414 | /** | ||
415 | * gigaset_skb_rcvd() - pass received skb to LL | ||
416 | * @bcs: B channel descriptor structure. | ||
417 | * @skb: received data. | ||
418 | * | ||
419 | * Called by hardware module {bas,ser,usb}_gigaset when user data has | ||
420 | * been successfully received, for passing to the LL. | ||
421 | * Warning: skb must not be accessed anymore! | ||
422 | */ | ||
423 | void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) | ||
424 | { | ||
425 | struct cardstate *cs = bcs->cs; | ||
426 | struct gigaset_capi_ctr *iif = cs->iif; | ||
427 | struct gigaset_capi_appl *ap = bcs->ap; | ||
428 | int len = skb->len; | ||
429 | |||
430 | /* update statistics */ | ||
431 | bcs->trans_down++; | ||
432 | |||
433 | if (!ap) { | ||
434 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
435 | return; | ||
436 | } | ||
437 | |||
438 | /* don't send further B3 messages if disconnected */ | ||
439 | if (ap->connected < APCONN_ACTIVE) { | ||
440 | gig_dbg(DEBUG_LLDATA, "disconnected, discarding data"); | ||
441 | dev_kfree_skb_any(skb); | ||
442 | return; | ||
443 | } | ||
444 | |||
445 | /* | ||
446 | * prepend DATA_B3_IND message to payload | ||
447 | * Parameters: NCCI = 1, all others 0/unused | ||
448 | * frequent message, avoid _cmsg overhead | ||
449 | */ | ||
450 | skb_push(skb, CAPI_DATA_B3_REQ_LEN); | ||
451 | CAPIMSG_SETLEN(skb->data, CAPI_DATA_B3_REQ_LEN); | ||
452 | CAPIMSG_SETAPPID(skb->data, ap->id); | ||
453 | CAPIMSG_SETCOMMAND(skb->data, CAPI_DATA_B3); | ||
454 | CAPIMSG_SETSUBCOMMAND(skb->data, CAPI_IND); | ||
455 | CAPIMSG_SETMSGID(skb->data, ap->nextMessageNumber++); | ||
456 | CAPIMSG_SETCONTROLLER(skb->data, iif->ctr.cnr); | ||
457 | CAPIMSG_SETPLCI_PART(skb->data, bcs->channel + 1); | ||
458 | CAPIMSG_SETNCCI_PART(skb->data, 1); | ||
459 | /* Data parameter not used */ | ||
460 | CAPIMSG_SETDATALEN(skb->data, len); | ||
461 | /* Data handle parameter not used */ | ||
462 | CAPIMSG_SETFLAGS(skb->data, 0); | ||
463 | /* Data64 parameter not present */ | ||
464 | |||
465 | /* emit message */ | ||
466 | dump_rawmsg(DEBUG_LLDATA, "DATA_B3_IND", skb->data); | ||
467 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
468 | } | ||
469 | EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); | ||
470 | |||
471 | /** | ||
472 | * gigaset_isdn_rcv_err() - signal receive error | ||
473 | * @bcs: B channel descriptor structure. | ||
474 | * | ||
475 | * Called by hardware module {bas,ser,usb}_gigaset when a receive error | ||
476 | * has occurred, for signalling to the LL. | ||
477 | */ | ||
478 | void gigaset_isdn_rcv_err(struct bc_state *bcs) | ||
479 | { | ||
480 | /* if currently ignoring packets, just count down */ | ||
481 | if (bcs->ignore) { | ||
482 | bcs->ignore--; | ||
483 | return; | ||
484 | } | ||
485 | |||
486 | /* update statistics */ | ||
487 | bcs->corrupted++; | ||
488 | |||
489 | /* ToDo: signal error -> LL */ | ||
490 | } | ||
491 | EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); | ||
492 | |||
493 | /** | ||
494 | * gigaset_isdn_icall() - signal incoming call | ||
495 | * @at_state: connection state structure. | ||
496 | * | ||
497 | * Called by main module at tasklet level to notify the LL that an incoming | ||
498 | * call has been received. @at_state contains the parameters of the call. | ||
499 | * | ||
500 | * Return value: call disposition (ICALL_*) | ||
501 | */ | ||
502 | int gigaset_isdn_icall(struct at_state_t *at_state) | ||
503 | { | ||
504 | struct cardstate *cs = at_state->cs; | ||
505 | struct bc_state *bcs = at_state->bcs; | ||
506 | struct gigaset_capi_ctr *iif = cs->iif; | ||
507 | struct gigaset_capi_appl *ap; | ||
508 | u32 actCIPmask; | ||
509 | struct sk_buff *skb; | ||
510 | unsigned int msgsize; | ||
511 | int i; | ||
512 | |||
513 | /* | ||
514 | * ToDo: signal calls without a free B channel, too | ||
515 | * (requires a u8 handle for the at_state structure that can | ||
516 | * be stored in the PLCI and used in the CONNECT_RESP message | ||
517 | * handler to retrieve it) | ||
518 | */ | ||
519 | if (!bcs) | ||
520 | return ICALL_IGNORE; | ||
521 | |||
522 | /* prepare CONNECT_IND message, using B channel number as PLCI */ | ||
523 | capi_cmsg_header(&iif->hcmsg, 0, CAPI_CONNECT, CAPI_IND, 0, | ||
524 | iif->ctr.cnr | ((bcs->channel + 1) << 8)); | ||
525 | |||
526 | /* minimum size, all structs empty */ | ||
527 | msgsize = CAPI_CONNECT_IND_BASELEN; | ||
528 | |||
529 | /* Bearer Capability (mandatory) */ | ||
530 | if (at_state->str_var[STR_ZBC]) { | ||
531 | /* pass on BC from Gigaset */ | ||
532 | if (encode_ie(at_state->str_var[STR_ZBC], iif->bc_buf, | ||
533 | MAX_BC_OCTETS) < 0) { | ||
534 | dev_warn(cs->dev, "RING ignored - bad BC %s\n", | ||
535 | at_state->str_var[STR_ZBC]); | ||
536 | return ICALL_IGNORE; | ||
537 | } | ||
538 | |||
539 | /* look up corresponding CIP value */ | ||
540 | iif->hcmsg.CIPValue = 0; /* default if nothing found */ | ||
541 | for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) | ||
542 | if (cip2bchlc[i].bc != NULL && | ||
543 | cip2bchlc[i].hlc == NULL && | ||
544 | !strcmp(cip2bchlc[i].bc, | ||
545 | at_state->str_var[STR_ZBC])) { | ||
546 | iif->hcmsg.CIPValue = i; | ||
547 | break; | ||
548 | } | ||
549 | } else { | ||
550 | /* no BC (internal call): assume CIP 1 (speech, A-law) */ | ||
551 | iif->hcmsg.CIPValue = 1; | ||
552 | encode_ie(cip2bchlc[1].bc, iif->bc_buf, MAX_BC_OCTETS); | ||
553 | } | ||
554 | iif->hcmsg.BC = iif->bc_buf; | ||
555 | msgsize += iif->hcmsg.BC[0]; | ||
556 | |||
557 | /* High Layer Compatibility (optional) */ | ||
558 | if (at_state->str_var[STR_ZHLC]) { | ||
559 | /* pass on HLC from Gigaset */ | ||
560 | if (encode_ie(at_state->str_var[STR_ZHLC], iif->hlc_buf, | ||
561 | MAX_HLC_OCTETS) < 0) { | ||
562 | dev_warn(cs->dev, "RING ignored - bad HLC %s\n", | ||
563 | at_state->str_var[STR_ZHLC]); | ||
564 | return ICALL_IGNORE; | ||
565 | } | ||
566 | iif->hcmsg.HLC = iif->hlc_buf; | ||
567 | msgsize += iif->hcmsg.HLC[0]; | ||
568 | |||
569 | /* look up corresponding CIP value */ | ||
570 | /* keep BC based CIP value if none found */ | ||
571 | if (at_state->str_var[STR_ZBC]) | ||
572 | for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) | ||
573 | if (cip2bchlc[i].hlc != NULL && | ||
574 | !strcmp(cip2bchlc[i].hlc, | ||
575 | at_state->str_var[STR_ZHLC]) && | ||
576 | !strcmp(cip2bchlc[i].bc, | ||
577 | at_state->str_var[STR_ZBC])) { | ||
578 | iif->hcmsg.CIPValue = i; | ||
579 | break; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | /* Called Party Number (optional) */ | ||
584 | if (at_state->str_var[STR_ZCPN]) { | ||
585 | i = strlen(at_state->str_var[STR_ZCPN]); | ||
586 | if (i > MAX_NUMBER_DIGITS) { | ||
587 | dev_warn(cs->dev, "RING ignored - bad number %s\n", | ||
588 | at_state->str_var[STR_ZBC]); | ||
589 | return ICALL_IGNORE; | ||
590 | } | ||
591 | iif->cdpty_buf[0] = i + 1; | ||
592 | iif->cdpty_buf[1] = 0x80; /* type / numbering plan unknown */ | ||
593 | memcpy(iif->cdpty_buf+2, at_state->str_var[STR_ZCPN], i); | ||
594 | iif->hcmsg.CalledPartyNumber = iif->cdpty_buf; | ||
595 | msgsize += iif->hcmsg.CalledPartyNumber[0]; | ||
596 | } | ||
597 | |||
598 | /* Calling Party Number (optional) */ | ||
599 | if (at_state->str_var[STR_NMBR]) { | ||
600 | i = strlen(at_state->str_var[STR_NMBR]); | ||
601 | if (i > MAX_NUMBER_DIGITS) { | ||
602 | dev_warn(cs->dev, "RING ignored - bad number %s\n", | ||
603 | at_state->str_var[STR_ZBC]); | ||
604 | return ICALL_IGNORE; | ||
605 | } | ||
606 | iif->cgpty_buf[0] = i + 2; | ||
607 | iif->cgpty_buf[1] = 0x00; /* type / numbering plan unknown */ | ||
608 | iif->cgpty_buf[2] = 0x80; /* pres. allowed, not screened */ | ||
609 | memcpy(iif->cgpty_buf+3, at_state->str_var[STR_NMBR], i); | ||
610 | iif->hcmsg.CallingPartyNumber = iif->cgpty_buf; | ||
611 | msgsize += iif->hcmsg.CallingPartyNumber[0]; | ||
612 | } | ||
613 | |||
614 | /* remaining parameters (not supported, always left NULL): | ||
615 | * - CalledPartySubaddress | ||
616 | * - CallingPartySubaddress | ||
617 | * - AdditionalInfo | ||
618 | * - BChannelinformation | ||
619 | * - Keypadfacility | ||
620 | * - Useruserdata | ||
621 | * - Facilitydataarray | ||
622 | */ | ||
623 | |||
624 | gig_dbg(DEBUG_CMD, "icall: PLCI %x CIP %d BC %s", | ||
625 | iif->hcmsg.adr.adrPLCI, iif->hcmsg.CIPValue, | ||
626 | format_ie(iif->hcmsg.BC)); | ||
627 | gig_dbg(DEBUG_CMD, "icall: HLC %s", | ||
628 | format_ie(iif->hcmsg.HLC)); | ||
629 | gig_dbg(DEBUG_CMD, "icall: CgPty %s", | ||
630 | format_ie(iif->hcmsg.CallingPartyNumber)); | ||
631 | gig_dbg(DEBUG_CMD, "icall: CdPty %s", | ||
632 | format_ie(iif->hcmsg.CalledPartyNumber)); | ||
633 | |||
634 | /* scan application list for matching listeners */ | ||
635 | bcs->ap = NULL; | ||
636 | actCIPmask = 1 | (1 << iif->hcmsg.CIPValue); | ||
637 | list_for_each_entry(ap, &iif->appls, ctrlist) | ||
638 | if (actCIPmask & ap->listenCIPmask) { | ||
639 | /* build CONNECT_IND message for this application */ | ||
640 | iif->hcmsg.ApplId = ap->id; | ||
641 | iif->hcmsg.Messagenumber = ap->nextMessageNumber++; | ||
642 | |||
643 | skb = alloc_skb(msgsize, GFP_ATOMIC); | ||
644 | if (!skb) { | ||
645 | dev_err(cs->dev, "%s: out of memory\n", | ||
646 | __func__); | ||
647 | break; | ||
648 | } | ||
649 | capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); | ||
650 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
651 | |||
652 | /* add to listeners on this B channel, update state */ | ||
653 | ap->bcnext = bcs->ap; | ||
654 | bcs->ap = ap; | ||
655 | bcs->chstate |= CHS_NOTIFY_LL; | ||
656 | ap->connected = APCONN_SETUP; | ||
657 | |||
658 | /* emit message */ | ||
659 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
660 | } | ||
661 | |||
662 | /* | ||
663 | * Return "accept" if any listeners. | ||
664 | * Gigaset will send ALERTING. | ||
665 | * There doesn't seem to be a way to avoid this. | ||
666 | */ | ||
667 | return bcs->ap ? ICALL_ACCEPT : ICALL_IGNORE; | ||
668 | } | ||
669 | |||
670 | /* | ||
671 | * send a DISCONNECT_IND message to an application | ||
672 | * does not sleep, clobbers the controller's hcmsg structure | ||
673 | */ | ||
674 | static void send_disconnect_ind(struct bc_state *bcs, | ||
675 | struct gigaset_capi_appl *ap, u16 reason) | ||
676 | { | ||
677 | struct cardstate *cs = bcs->cs; | ||
678 | struct gigaset_capi_ctr *iif = cs->iif; | ||
679 | struct sk_buff *skb; | ||
680 | |||
681 | if (ap->connected == APCONN_NONE) | ||
682 | return; | ||
683 | |||
684 | capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, | ||
685 | ap->nextMessageNumber++, | ||
686 | iif->ctr.cnr | ((bcs->channel + 1) << 8)); | ||
687 | iif->hcmsg.Reason = reason; | ||
688 | skb = alloc_skb(CAPI_DISCONNECT_IND_LEN, GFP_ATOMIC); | ||
689 | if (!skb) { | ||
690 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
691 | return; | ||
692 | } | ||
693 | capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN)); | ||
694 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
695 | ap->connected = APCONN_NONE; | ||
696 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
697 | } | ||
698 | |||
699 | /* | ||
700 | * send a DISCONNECT_B3_IND message to an application | ||
701 | * Parameters: NCCI = 1, NCPI empty, Reason_B3 = 0 | ||
702 | * does not sleep, clobbers the controller's hcmsg structure | ||
703 | */ | ||
704 | static void send_disconnect_b3_ind(struct bc_state *bcs, | ||
705 | struct gigaset_capi_appl *ap) | ||
706 | { | ||
707 | struct cardstate *cs = bcs->cs; | ||
708 | struct gigaset_capi_ctr *iif = cs->iif; | ||
709 | struct sk_buff *skb; | ||
710 | |||
711 | /* nothing to do if no logical connection active */ | ||
712 | if (ap->connected < APCONN_ACTIVE) | ||
713 | return; | ||
714 | ap->connected = APCONN_SETUP; | ||
715 | |||
716 | capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, | ||
717 | ap->nextMessageNumber++, | ||
718 | iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); | ||
719 | skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_ATOMIC); | ||
720 | if (!skb) { | ||
721 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
722 | return; | ||
723 | } | ||
724 | capi_cmsg2message(&iif->hcmsg, | ||
725 | __skb_put(skb, CAPI_DISCONNECT_B3_IND_BASELEN)); | ||
726 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
727 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
728 | } | ||
729 | |||
730 | /** | ||
731 | * gigaset_isdn_connD() - signal D channel connect | ||
732 | * @bcs: B channel descriptor structure. | ||
733 | * | ||
734 | * Called by main module at tasklet level to notify the LL that the D channel | ||
735 | * connection has been established. | ||
736 | */ | ||
737 | void gigaset_isdn_connD(struct bc_state *bcs) | ||
738 | { | ||
739 | struct cardstate *cs = bcs->cs; | ||
740 | struct gigaset_capi_ctr *iif = cs->iif; | ||
741 | struct gigaset_capi_appl *ap = bcs->ap; | ||
742 | struct sk_buff *skb; | ||
743 | unsigned int msgsize; | ||
744 | |||
745 | if (!ap) { | ||
746 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
747 | return; | ||
748 | } | ||
749 | while (ap->bcnext) { | ||
750 | /* this should never happen */ | ||
751 | dev_warn(cs->dev, "%s: dropping extra application %u\n", | ||
752 | __func__, ap->bcnext->id); | ||
753 | send_disconnect_ind(bcs, ap->bcnext, | ||
754 | CapiCallGivenToOtherApplication); | ||
755 | ap->bcnext = ap->bcnext->bcnext; | ||
756 | } | ||
757 | if (ap->connected == APCONN_NONE) { | ||
758 | dev_warn(cs->dev, "%s: application %u not connected\n", | ||
759 | __func__, ap->id); | ||
760 | return; | ||
761 | } | ||
762 | |||
763 | /* prepare CONNECT_ACTIVE_IND message | ||
764 | * Note: LLC not supported by device | ||
765 | */ | ||
766 | capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_CONNECT_ACTIVE, CAPI_IND, | ||
767 | ap->nextMessageNumber++, | ||
768 | iif->ctr.cnr | ((bcs->channel + 1) << 8)); | ||
769 | |||
770 | /* minimum size, all structs empty */ | ||
771 | msgsize = CAPI_CONNECT_ACTIVE_IND_BASELEN; | ||
772 | |||
773 | /* ToDo: set parameter: Connected number | ||
774 | * (requires ev-layer state machine extension to collect | ||
775 | * ZCON device reply) | ||
776 | */ | ||
777 | |||
778 | /* build and emit CONNECT_ACTIVE_IND message */ | ||
779 | skb = alloc_skb(msgsize, GFP_ATOMIC); | ||
780 | if (!skb) { | ||
781 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
782 | return; | ||
783 | } | ||
784 | capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); | ||
785 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
786 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
787 | } | ||
788 | |||
789 | /** | ||
790 | * gigaset_isdn_hupD() - signal D channel hangup | ||
791 | * @bcs: B channel descriptor structure. | ||
792 | * | ||
793 | * Called by main module at tasklet level to notify the LL that the D channel | ||
794 | * connection has been shut down. | ||
795 | */ | ||
796 | void gigaset_isdn_hupD(struct bc_state *bcs) | ||
797 | { | ||
798 | struct gigaset_capi_appl *ap; | ||
799 | |||
800 | /* | ||
801 | * ToDo: pass on reason code reported by device | ||
802 | * (requires ev-layer state machine extension to collect | ||
803 | * ZCAU device reply) | ||
804 | */ | ||
805 | for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) { | ||
806 | send_disconnect_b3_ind(bcs, ap); | ||
807 | send_disconnect_ind(bcs, ap, 0); | ||
808 | } | ||
809 | bcs->ap = NULL; | ||
810 | } | ||
811 | |||
812 | /** | ||
813 | * gigaset_isdn_connB() - signal B channel connect | ||
814 | * @bcs: B channel descriptor structure. | ||
815 | * | ||
816 | * Called by main module at tasklet level to notify the LL that the B channel | ||
817 | * connection has been established. | ||
818 | */ | ||
819 | void gigaset_isdn_connB(struct bc_state *bcs) | ||
820 | { | ||
821 | struct cardstate *cs = bcs->cs; | ||
822 | struct gigaset_capi_ctr *iif = cs->iif; | ||
823 | struct gigaset_capi_appl *ap = bcs->ap; | ||
824 | struct sk_buff *skb; | ||
825 | unsigned int msgsize; | ||
826 | u8 command; | ||
827 | |||
828 | if (!ap) { | ||
829 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
830 | return; | ||
831 | } | ||
832 | while (ap->bcnext) { | ||
833 | /* this should never happen */ | ||
834 | dev_warn(cs->dev, "%s: dropping extra application %u\n", | ||
835 | __func__, ap->bcnext->id); | ||
836 | send_disconnect_ind(bcs, ap->bcnext, | ||
837 | CapiCallGivenToOtherApplication); | ||
838 | ap->bcnext = ap->bcnext->bcnext; | ||
839 | } | ||
840 | if (!ap->connected) { | ||
841 | dev_warn(cs->dev, "%s: application %u not connected\n", | ||
842 | __func__, ap->id); | ||
843 | return; | ||
844 | } | ||
845 | |||
846 | /* | ||
847 | * emit CONNECT_B3_ACTIVE_IND if we already got CONNECT_B3_REQ; | ||
848 | * otherwise we have to emit CONNECT_B3_IND first, and follow up with | ||
849 | * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP | ||
850 | * Parameters in both cases always: NCCI = 1, NCPI empty | ||
851 | */ | ||
852 | if (ap->connected >= APCONN_ACTIVE) { | ||
853 | command = CAPI_CONNECT_B3_ACTIVE; | ||
854 | msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; | ||
855 | } else { | ||
856 | command = CAPI_CONNECT_B3; | ||
857 | msgsize = CAPI_CONNECT_B3_IND_BASELEN; | ||
858 | } | ||
859 | capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND, | ||
860 | ap->nextMessageNumber++, | ||
861 | iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); | ||
862 | skb = alloc_skb(msgsize, GFP_ATOMIC); | ||
863 | if (!skb) { | ||
864 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
865 | return; | ||
866 | } | ||
867 | capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); | ||
868 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
869 | ap->connected = APCONN_ACTIVE; | ||
870 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
871 | } | ||
872 | |||
873 | /** | ||
874 | * gigaset_isdn_hupB() - signal B channel hangup | ||
875 | * @bcs: B channel descriptor structure. | ||
876 | * | ||
877 | * Called by main module to notify the LL that the B channel connection has | ||
878 | * been shut down. | ||
879 | */ | ||
880 | void gigaset_isdn_hupB(struct bc_state *bcs) | ||
881 | { | ||
882 | struct cardstate *cs = bcs->cs; | ||
883 | struct gigaset_capi_appl *ap = bcs->ap; | ||
884 | |||
885 | /* ToDo: assure order of DISCONNECT_B3_IND and DISCONNECT_IND ? */ | ||
886 | |||
887 | if (!ap) { | ||
888 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
889 | return; | ||
890 | } | ||
891 | |||
892 | send_disconnect_b3_ind(bcs, ap); | ||
893 | } | ||
894 | |||
895 | /** | ||
896 | * gigaset_isdn_start() - signal device availability | ||
897 | * @cs: device descriptor structure. | ||
898 | * | ||
899 | * Called by main module to notify the LL that the device is available for | ||
900 | * use. | ||
901 | */ | ||
902 | void gigaset_isdn_start(struct cardstate *cs) | ||
903 | { | ||
904 | struct gigaset_capi_ctr *iif = cs->iif; | ||
905 | |||
906 | /* fill profile data: manufacturer name */ | ||
907 | strcpy(iif->ctr.manu, "Siemens"); | ||
908 | /* CAPI and device version */ | ||
909 | iif->ctr.version.majorversion = 2; /* CAPI 2.0 */ | ||
910 | iif->ctr.version.minorversion = 0; | ||
911 | /* ToDo: check/assert cs->gotfwver? */ | ||
912 | iif->ctr.version.majormanuversion = cs->fwver[0]; | ||
913 | iif->ctr.version.minormanuversion = cs->fwver[1]; | ||
914 | /* number of B channels supported */ | ||
915 | iif->ctr.profile.nbchannel = cs->channels; | ||
916 | /* global options: internal controller, supplementary services */ | ||
917 | iif->ctr.profile.goptions = 0x11; | ||
918 | /* B1 protocols: 64 kbit/s HDLC or transparent */ | ||
919 | iif->ctr.profile.support1 = 0x03; | ||
920 | /* B2 protocols: transparent only */ | ||
921 | /* ToDo: X.75 SLP ? */ | ||
922 | iif->ctr.profile.support2 = 0x02; | ||
923 | /* B3 protocols: transparent only */ | ||
924 | iif->ctr.profile.support3 = 0x01; | ||
925 | /* no serial number */ | ||
926 | strcpy(iif->ctr.serial, "0"); | ||
927 | capi_ctr_ready(&iif->ctr); | ||
928 | } | ||
929 | |||
930 | /** | ||
931 | * gigaset_isdn_stop() - signal device unavailability | ||
932 | * @cs: device descriptor structure. | ||
933 | * | ||
934 | * Called by main module to notify the LL that the device is no longer | ||
935 | * available for use. | ||
936 | */ | ||
937 | void gigaset_isdn_stop(struct cardstate *cs) | ||
938 | { | ||
939 | struct gigaset_capi_ctr *iif = cs->iif; | ||
940 | capi_ctr_down(&iif->ctr); | ||
941 | } | ||
942 | |||
943 | /* | ||
944 | * kernel CAPI callback methods | ||
945 | * ============================ | ||
946 | */ | ||
947 | |||
948 | /* | ||
949 | * load firmware | ||
950 | */ | ||
951 | static int gigaset_load_firmware(struct capi_ctr *ctr, capiloaddata *data) | ||
952 | { | ||
953 | struct cardstate *cs = ctr->driverdata; | ||
954 | |||
955 | /* AVM specific operation, not needed for Gigaset -- ignore */ | ||
956 | dev_notice(cs->dev, "load_firmware ignored\n"); | ||
957 | |||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | /* | ||
962 | * reset (deactivate) controller | ||
963 | */ | ||
964 | static void gigaset_reset_ctr(struct capi_ctr *ctr) | ||
965 | { | ||
966 | struct cardstate *cs = ctr->driverdata; | ||
967 | |||
968 | /* AVM specific operation, not needed for Gigaset -- ignore */ | ||
969 | dev_notice(cs->dev, "reset_ctr ignored\n"); | ||
970 | } | ||
971 | |||
972 | /* | ||
973 | * register CAPI application | ||
974 | */ | ||
975 | static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, | ||
976 | capi_register_params *rp) | ||
977 | { | ||
978 | struct gigaset_capi_ctr *iif | ||
979 | = container_of(ctr, struct gigaset_capi_ctr, ctr); | ||
980 | struct cardstate *cs = ctr->driverdata; | ||
981 | struct gigaset_capi_appl *ap; | ||
982 | |||
983 | list_for_each_entry(ap, &iif->appls, ctrlist) | ||
984 | if (ap->id == appl) { | ||
985 | dev_notice(cs->dev, | ||
986 | "application %u already registered\n", appl); | ||
987 | return; | ||
988 | } | ||
989 | |||
990 | ap = kzalloc(sizeof(*ap), GFP_KERNEL); | ||
991 | if (!ap) { | ||
992 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
993 | return; | ||
994 | } | ||
995 | ap->id = appl; | ||
996 | |||
997 | list_add(&ap->ctrlist, &iif->appls); | ||
998 | } | ||
999 | |||
1000 | /* | ||
1001 | * release CAPI application | ||
1002 | */ | ||
1003 | static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl) | ||
1004 | { | ||
1005 | struct gigaset_capi_ctr *iif | ||
1006 | = container_of(ctr, struct gigaset_capi_ctr, ctr); | ||
1007 | struct cardstate *cs = iif->ctr.driverdata; | ||
1008 | struct gigaset_capi_appl *ap, *tmp; | ||
1009 | |||
1010 | list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist) | ||
1011 | if (ap->id == appl) { | ||
1012 | if (ap->connected != APCONN_NONE) { | ||
1013 | dev_err(cs->dev, | ||
1014 | "%s: application %u still connected\n", | ||
1015 | __func__, ap->id); | ||
1016 | /* ToDo: clear active connection */ | ||
1017 | } | ||
1018 | list_del(&ap->ctrlist); | ||
1019 | kfree(ap); | ||
1020 | } | ||
1021 | |||
1022 | } | ||
1023 | |||
1024 | /* | ||
1025 | * ===================================================================== | ||
1026 | * outgoing CAPI message handler | ||
1027 | * ===================================================================== | ||
1028 | */ | ||
1029 | |||
1030 | /* | ||
1031 | * helper function: emit reply message with given Info value | ||
1032 | */ | ||
1033 | static void send_conf(struct gigaset_capi_ctr *iif, | ||
1034 | struct gigaset_capi_appl *ap, | ||
1035 | struct sk_buff *skb, | ||
1036 | u16 info) | ||
1037 | { | ||
1038 | /* | ||
1039 | * _CONF replies always only have NCCI and Info parameters | ||
1040 | * so they'll fit into the _REQ message skb | ||
1041 | */ | ||
1042 | capi_cmsg_answer(&iif->acmsg); | ||
1043 | iif->acmsg.Info = info; | ||
1044 | capi_cmsg2message(&iif->acmsg, skb->data); | ||
1045 | __skb_trim(skb, CAPI_STDCONF_LEN); | ||
1046 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1047 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
1048 | } | ||
1049 | |||
1050 | /* | ||
1051 | * process FACILITY_REQ message | ||
1052 | */ | ||
1053 | static void do_facility_req(struct gigaset_capi_ctr *iif, | ||
1054 | struct gigaset_capi_appl *ap, | ||
1055 | struct sk_buff *skb) | ||
1056 | { | ||
1057 | struct cardstate *cs = iif->ctr.driverdata; | ||
1058 | _cmsg *cmsg = &iif->acmsg; | ||
1059 | struct sk_buff *cskb; | ||
1060 | u8 *pparam; | ||
1061 | unsigned int msgsize = CAPI_FACILITY_CONF_BASELEN; | ||
1062 | u16 function, info; | ||
1063 | static u8 confparam[10]; /* max. 9 octets + length byte */ | ||
1064 | |||
1065 | /* decode message */ | ||
1066 | capi_message2cmsg(cmsg, skb->data); | ||
1067 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1068 | |||
1069 | /* | ||
1070 | * Facility Request Parameter is not decoded by capi_message2cmsg() | ||
1071 | * encoding depends on Facility Selector | ||
1072 | */ | ||
1073 | switch (cmsg->FacilitySelector) { | ||
1074 | case CAPI_FACILITY_DTMF: /* ToDo */ | ||
1075 | info = CapiFacilityNotSupported; | ||
1076 | confparam[0] = 2; /* length */ | ||
1077 | /* DTMF information: Unknown DTMF request */ | ||
1078 | capimsg_setu16(confparam, 1, 2); | ||
1079 | break; | ||
1080 | |||
1081 | case CAPI_FACILITY_V42BIS: /* not supported */ | ||
1082 | info = CapiFacilityNotSupported; | ||
1083 | confparam[0] = 2; /* length */ | ||
1084 | /* V.42 bis information: not available */ | ||
1085 | capimsg_setu16(confparam, 1, 1); | ||
1086 | break; | ||
1087 | |||
1088 | case CAPI_FACILITY_SUPPSVC: | ||
1089 | /* decode Function parameter */ | ||
1090 | pparam = cmsg->FacilityRequestParameter; | ||
1091 | if (pparam == NULL || *pparam < 2) { | ||
1092 | dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ", | ||
1093 | "Facility Request Parameter"); | ||
1094 | send_conf(iif, ap, skb, CapiIllMessageParmCoding); | ||
1095 | return; | ||
1096 | } | ||
1097 | function = CAPIMSG_U16(pparam, 1); | ||
1098 | switch (function) { | ||
1099 | case CAPI_SUPPSVC_GETSUPPORTED: | ||
1100 | info = CapiSuccess; | ||
1101 | /* Supplementary Service specific parameter */ | ||
1102 | confparam[3] = 6; /* length */ | ||
1103 | /* Supplementary services info: Success */ | ||
1104 | capimsg_setu16(confparam, 4, CapiSuccess); | ||
1105 | /* Supported Services: none */ | ||
1106 | capimsg_setu32(confparam, 6, 0); | ||
1107 | break; | ||
1108 | /* ToDo: add supported services */ | ||
1109 | default: | ||
1110 | info = CapiFacilitySpecificFunctionNotSupported; | ||
1111 | /* Supplementary Service specific parameter */ | ||
1112 | confparam[3] = 2; /* length */ | ||
1113 | /* Supplementary services info: not supported */ | ||
1114 | capimsg_setu16(confparam, 4, | ||
1115 | CapiSupplementaryServiceNotSupported); | ||
1116 | } | ||
1117 | |||
1118 | /* Facility confirmation parameter */ | ||
1119 | confparam[0] = confparam[3] + 3; /* total length */ | ||
1120 | /* Function: copy from _REQ message */ | ||
1121 | capimsg_setu16(confparam, 1, function); | ||
1122 | /* Supplementary Service specific parameter already set above */ | ||
1123 | break; | ||
1124 | |||
1125 | case CAPI_FACILITY_WAKEUP: /* ToDo */ | ||
1126 | info = CapiFacilityNotSupported; | ||
1127 | confparam[0] = 2; /* length */ | ||
1128 | /* Number of accepted awake request parameters: 0 */ | ||
1129 | capimsg_setu16(confparam, 1, 0); | ||
1130 | break; | ||
1131 | |||
1132 | default: | ||
1133 | info = CapiFacilityNotSupported; | ||
1134 | confparam[0] = 0; /* empty struct */ | ||
1135 | } | ||
1136 | |||
1137 | /* send FACILITY_CONF with given Info and confirmation parameter */ | ||
1138 | capi_cmsg_answer(cmsg); | ||
1139 | cmsg->Info = info; | ||
1140 | cmsg->FacilityConfirmationParameter = confparam; | ||
1141 | msgsize += confparam[0]; /* length */ | ||
1142 | cskb = alloc_skb(msgsize, GFP_ATOMIC); | ||
1143 | if (!cskb) { | ||
1144 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1145 | return; | ||
1146 | } | ||
1147 | capi_cmsg2message(cmsg, __skb_put(cskb, msgsize)); | ||
1148 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1149 | capi_ctr_handle_message(&iif->ctr, ap->id, cskb); | ||
1150 | } | ||
1151 | |||
1152 | |||
1153 | /* | ||
1154 | * process LISTEN_REQ message | ||
1155 | * just store the masks in the application data structure | ||
1156 | */ | ||
1157 | static void do_listen_req(struct gigaset_capi_ctr *iif, | ||
1158 | struct gigaset_capi_appl *ap, | ||
1159 | struct sk_buff *skb) | ||
1160 | { | ||
1161 | /* decode message */ | ||
1162 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1163 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1164 | |||
1165 | /* store listening parameters */ | ||
1166 | ap->listenInfoMask = iif->acmsg.InfoMask; | ||
1167 | ap->listenCIPmask = iif->acmsg.CIPmask; | ||
1168 | send_conf(iif, ap, skb, CapiSuccess); | ||
1169 | } | ||
1170 | |||
1171 | /* | ||
1172 | * process ALERT_REQ message | ||
1173 | * nothing to do, Gigaset always alerts anyway | ||
1174 | */ | ||
1175 | static void do_alert_req(struct gigaset_capi_ctr *iif, | ||
1176 | struct gigaset_capi_appl *ap, | ||
1177 | struct sk_buff *skb) | ||
1178 | { | ||
1179 | /* decode message */ | ||
1180 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1181 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1182 | send_conf(iif, ap, skb, CapiAlertAlreadySent); | ||
1183 | } | ||
1184 | |||
1185 | /* | ||
1186 | * process CONNECT_REQ message | ||
1187 | * allocate a B channel, prepare dial commands, queue a DIAL event, | ||
1188 | * emit CONNECT_CONF reply | ||
1189 | */ | ||
1190 | static void do_connect_req(struct gigaset_capi_ctr *iif, | ||
1191 | struct gigaset_capi_appl *ap, | ||
1192 | struct sk_buff *skb) | ||
1193 | { | ||
1194 | struct cardstate *cs = iif->ctr.driverdata; | ||
1195 | _cmsg *cmsg = &iif->acmsg; | ||
1196 | struct bc_state *bcs; | ||
1197 | char **commands; | ||
1198 | char *s; | ||
1199 | u8 *pp; | ||
1200 | int i, l; | ||
1201 | u16 info; | ||
1202 | |||
1203 | /* decode message */ | ||
1204 | capi_message2cmsg(cmsg, skb->data); | ||
1205 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1206 | |||
1207 | /* get free B channel & construct PLCI */ | ||
1208 | bcs = gigaset_get_free_channel(cs); | ||
1209 | if (!bcs) { | ||
1210 | dev_notice(cs->dev, "%s: no B channel available\n", | ||
1211 | "CONNECT_REQ"); | ||
1212 | send_conf(iif, ap, skb, CapiNoPlciAvailable); | ||
1213 | return; | ||
1214 | } | ||
1215 | ap->bcnext = NULL; | ||
1216 | bcs->ap = ap; | ||
1217 | cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; | ||
1218 | |||
1219 | /* build command table */ | ||
1220 | commands = kzalloc(AT_NUM*(sizeof *commands), GFP_KERNEL); | ||
1221 | if (!commands) | ||
1222 | goto oom; | ||
1223 | |||
1224 | /* encode parameter: Called party number */ | ||
1225 | pp = cmsg->CalledPartyNumber; | ||
1226 | if (pp == NULL || *pp == 0) { | ||
1227 | dev_notice(cs->dev, "%s: %s missing\n", | ||
1228 | "CONNECT_REQ", "Called party number"); | ||
1229 | info = CapiIllMessageParmCoding; | ||
1230 | goto error; | ||
1231 | } | ||
1232 | l = *pp++; | ||
1233 | /* check type of number/numbering plan byte */ | ||
1234 | switch (*pp) { | ||
1235 | case 0x80: /* unknown type / unknown numbering plan */ | ||
1236 | case 0x81: /* unknown type / ISDN/Telephony numbering plan */ | ||
1237 | break; | ||
1238 | default: /* others: warn about potential misinterpretation */ | ||
1239 | dev_notice(cs->dev, "%s: %s type/plan 0x%02x unsupported\n", | ||
1240 | "CONNECT_REQ", "Called party number", *pp); | ||
1241 | } | ||
1242 | pp++; | ||
1243 | l--; | ||
1244 | /* translate "**" internal call prefix to CTP value */ | ||
1245 | if (l >= 2 && pp[0] == '*' && pp[1] == '*') { | ||
1246 | s = "^SCTP=0\r"; | ||
1247 | pp += 2; | ||
1248 | l -= 2; | ||
1249 | } else { | ||
1250 | s = "^SCTP=1\r"; | ||
1251 | } | ||
1252 | commands[AT_TYPE] = kstrdup(s, GFP_KERNEL); | ||
1253 | if (!commands[AT_TYPE]) | ||
1254 | goto oom; | ||
1255 | commands[AT_DIAL] = kmalloc(l+3, GFP_KERNEL); | ||
1256 | if (!commands[AT_DIAL]) | ||
1257 | goto oom; | ||
1258 | snprintf(commands[AT_DIAL], l+3, "D%.*s\r", l, pp); | ||
1259 | |||
1260 | /* encode parameter: Calling party number */ | ||
1261 | pp = cmsg->CallingPartyNumber; | ||
1262 | if (pp != NULL && *pp > 0) { | ||
1263 | l = *pp++; | ||
1264 | |||
1265 | /* check type of number/numbering plan byte */ | ||
1266 | /* ToDo: allow for/handle Ext=1? */ | ||
1267 | switch (*pp) { | ||
1268 | case 0x00: /* unknown type / unknown numbering plan */ | ||
1269 | case 0x01: /* unknown type / ISDN/Telephony num. plan */ | ||
1270 | break; | ||
1271 | default: | ||
1272 | dev_notice(cs->dev, | ||
1273 | "%s: %s type/plan 0x%02x unsupported\n", | ||
1274 | "CONNECT_REQ", "Calling party number", *pp); | ||
1275 | } | ||
1276 | pp++; | ||
1277 | l--; | ||
1278 | |||
1279 | /* check presentation indicator */ | ||
1280 | if (!l) { | ||
1281 | dev_notice(cs->dev, "%s: %s IE truncated\n", | ||
1282 | "CONNECT_REQ", "Calling party number"); | ||
1283 | info = CapiIllMessageParmCoding; | ||
1284 | goto error; | ||
1285 | } | ||
1286 | switch (*pp & 0xfc) { /* ignore Screening indicator */ | ||
1287 | case 0x80: /* Presentation allowed */ | ||
1288 | s = "^SCLIP=1\r"; | ||
1289 | break; | ||
1290 | case 0xa0: /* Presentation restricted */ | ||
1291 | s = "^SCLIP=0\r"; | ||
1292 | break; | ||
1293 | default: | ||
1294 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1295 | "CONNECT_REQ", | ||
1296 | "Presentation/Screening indicator", | ||
1297 | *pp); | ||
1298 | s = "^SCLIP=1\r"; | ||
1299 | } | ||
1300 | commands[AT_CLIP] = kstrdup(s, GFP_KERNEL); | ||
1301 | if (!commands[AT_CLIP]) | ||
1302 | goto oom; | ||
1303 | pp++; | ||
1304 | l--; | ||
1305 | |||
1306 | if (l) { | ||
1307 | /* number */ | ||
1308 | commands[AT_MSN] = kmalloc(l+8, GFP_KERNEL); | ||
1309 | if (!commands[AT_MSN]) | ||
1310 | goto oom; | ||
1311 | snprintf(commands[AT_MSN], l+8, "^SMSN=%*s\r", l, pp); | ||
1312 | } | ||
1313 | } | ||
1314 | |||
1315 | /* check parameter: CIP Value */ | ||
1316 | if (cmsg->CIPValue > ARRAY_SIZE(cip2bchlc) || | ||
1317 | (cmsg->CIPValue > 0 && cip2bchlc[cmsg->CIPValue].bc == NULL)) { | ||
1318 | dev_notice(cs->dev, "%s: unknown CIP value %d\n", | ||
1319 | "CONNECT_REQ", cmsg->CIPValue); | ||
1320 | info = CapiCipValueUnknown; | ||
1321 | goto error; | ||
1322 | } | ||
1323 | |||
1324 | /* check/encode parameter: BC */ | ||
1325 | if (cmsg->BC && cmsg->BC[0]) { | ||
1326 | /* explicit BC overrides CIP */ | ||
1327 | l = 2*cmsg->BC[0] + 7; | ||
1328 | commands[AT_BC] = kmalloc(l, GFP_KERNEL); | ||
1329 | if (!commands[AT_BC]) | ||
1330 | goto oom; | ||
1331 | strcpy(commands[AT_BC], "^SBC="); | ||
1332 | decode_ie(cmsg->BC, commands[AT_BC]+5); | ||
1333 | strcpy(commands[AT_BC] + l - 2, "\r"); | ||
1334 | } else if (cip2bchlc[cmsg->CIPValue].bc) { | ||
1335 | l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7; | ||
1336 | commands[AT_BC] = kmalloc(l, GFP_KERNEL); | ||
1337 | if (!commands[AT_BC]) | ||
1338 | goto oom; | ||
1339 | snprintf(commands[AT_BC], l, "^SBC=%s\r", | ||
1340 | cip2bchlc[cmsg->CIPValue].bc); | ||
1341 | } | ||
1342 | |||
1343 | /* check/encode parameter: HLC */ | ||
1344 | if (cmsg->HLC && cmsg->HLC[0]) { | ||
1345 | /* explicit HLC overrides CIP */ | ||
1346 | l = 2*cmsg->HLC[0] + 7; | ||
1347 | commands[AT_HLC] = kmalloc(l, GFP_KERNEL); | ||
1348 | if (!commands[AT_HLC]) | ||
1349 | goto oom; | ||
1350 | strcpy(commands[AT_HLC], "^SHLC="); | ||
1351 | decode_ie(cmsg->HLC, commands[AT_HLC]+5); | ||
1352 | strcpy(commands[AT_HLC] + l - 2, "\r"); | ||
1353 | } else if (cip2bchlc[cmsg->CIPValue].hlc) { | ||
1354 | l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7; | ||
1355 | commands[AT_HLC] = kmalloc(l, GFP_KERNEL); | ||
1356 | if (!commands[AT_HLC]) | ||
1357 | goto oom; | ||
1358 | snprintf(commands[AT_HLC], l, "^SHLC=%s\r", | ||
1359 | cip2bchlc[cmsg->CIPValue].hlc); | ||
1360 | } | ||
1361 | |||
1362 | /* check/encode parameter: B Protocol */ | ||
1363 | if (cmsg->BProtocol == CAPI_DEFAULT) { | ||
1364 | bcs->proto2 = L2_HDLC; | ||
1365 | dev_warn(cs->dev, | ||
1366 | "B2 Protocol X.75 SLP unsupported, using Transparent\n"); | ||
1367 | } else { | ||
1368 | switch (cmsg->B1protocol) { | ||
1369 | case 0: | ||
1370 | bcs->proto2 = L2_HDLC; | ||
1371 | break; | ||
1372 | case 1: | ||
1373 | bcs->proto2 = L2_BITSYNC; | ||
1374 | break; | ||
1375 | default: | ||
1376 | dev_warn(cs->dev, | ||
1377 | "B1 Protocol %u unsupported, using Transparent\n", | ||
1378 | cmsg->B1protocol); | ||
1379 | bcs->proto2 = L2_BITSYNC; | ||
1380 | } | ||
1381 | if (cmsg->B2protocol != 1) | ||
1382 | dev_warn(cs->dev, | ||
1383 | "B2 Protocol %u unsupported, using Transparent\n", | ||
1384 | cmsg->B2protocol); | ||
1385 | if (cmsg->B3protocol != 0) | ||
1386 | dev_warn(cs->dev, | ||
1387 | "B3 Protocol %u unsupported, using Transparent\n", | ||
1388 | cmsg->B3protocol); | ||
1389 | ignore_cstruct_param(cs, cmsg->B1configuration, | ||
1390 | "CONNECT_REQ", "B1 Configuration"); | ||
1391 | ignore_cstruct_param(cs, cmsg->B2configuration, | ||
1392 | "CONNECT_REQ", "B2 Configuration"); | ||
1393 | ignore_cstruct_param(cs, cmsg->B3configuration, | ||
1394 | "CONNECT_REQ", "B3 Configuration"); | ||
1395 | } | ||
1396 | commands[AT_PROTO] = kmalloc(9, GFP_KERNEL); | ||
1397 | if (!commands[AT_PROTO]) | ||
1398 | goto oom; | ||
1399 | snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); | ||
1400 | |||
1401 | /* ToDo: check/encode remaining parameters */ | ||
1402 | ignore_cstruct_param(cs, cmsg->CalledPartySubaddress, | ||
1403 | "CONNECT_REQ", "Called pty subaddr"); | ||
1404 | ignore_cstruct_param(cs, cmsg->CallingPartySubaddress, | ||
1405 | "CONNECT_REQ", "Calling pty subaddr"); | ||
1406 | ignore_cstruct_param(cs, cmsg->LLC, | ||
1407 | "CONNECT_REQ", "LLC"); | ||
1408 | if (cmsg->AdditionalInfo != CAPI_DEFAULT) { | ||
1409 | ignore_cstruct_param(cs, cmsg->BChannelinformation, | ||
1410 | "CONNECT_REQ", "B Channel Information"); | ||
1411 | ignore_cstruct_param(cs, cmsg->Keypadfacility, | ||
1412 | "CONNECT_REQ", "Keypad Facility"); | ||
1413 | ignore_cstruct_param(cs, cmsg->Useruserdata, | ||
1414 | "CONNECT_REQ", "User-User Data"); | ||
1415 | ignore_cstruct_param(cs, cmsg->Facilitydataarray, | ||
1416 | "CONNECT_REQ", "Facility Data Array"); | ||
1417 | } | ||
1418 | |||
1419 | /* encode parameter: B channel to use */ | ||
1420 | commands[AT_ISO] = kmalloc(9, GFP_KERNEL); | ||
1421 | if (!commands[AT_ISO]) | ||
1422 | goto oom; | ||
1423 | snprintf(commands[AT_ISO], 9, "^SISO=%u\r", | ||
1424 | (unsigned) bcs->channel + 1); | ||
1425 | |||
1426 | /* queue & schedule EV_DIAL event */ | ||
1427 | if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, | ||
1428 | bcs->at_state.seq_index, NULL)) | ||
1429 | goto oom; | ||
1430 | gig_dbg(DEBUG_CMD, "scheduling DIAL"); | ||
1431 | gigaset_schedule_event(cs); | ||
1432 | ap->connected = APCONN_SETUP; | ||
1433 | send_conf(iif, ap, skb, CapiSuccess); | ||
1434 | return; | ||
1435 | |||
1436 | oom: | ||
1437 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1438 | info = CAPI_MSGOSRESOURCEERR; | ||
1439 | error: | ||
1440 | if (commands) | ||
1441 | for (i = 0; i < AT_NUM; i++) | ||
1442 | kfree(commands[i]); | ||
1443 | kfree(commands); | ||
1444 | gigaset_free_channel(bcs); | ||
1445 | send_conf(iif, ap, skb, info); | ||
1446 | } | ||
1447 | |||
1448 | /* | ||
1449 | * process CONNECT_RESP message | ||
1450 | * checks protocol parameters and queues an ACCEPT or HUP event | ||
1451 | */ | ||
1452 | static void do_connect_resp(struct gigaset_capi_ctr *iif, | ||
1453 | struct gigaset_capi_appl *ap, | ||
1454 | struct sk_buff *skb) | ||
1455 | { | ||
1456 | struct cardstate *cs = iif->ctr.driverdata; | ||
1457 | _cmsg *cmsg = &iif->acmsg; | ||
1458 | struct bc_state *bcs; | ||
1459 | struct gigaset_capi_appl *oap; | ||
1460 | int channel; | ||
1461 | |||
1462 | /* decode message */ | ||
1463 | capi_message2cmsg(cmsg, skb->data); | ||
1464 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1465 | dev_kfree_skb_any(skb); | ||
1466 | |||
1467 | /* extract and check channel number from PLCI */ | ||
1468 | channel = (cmsg->adr.adrPLCI >> 8) & 0xff; | ||
1469 | if (!channel || channel > cs->channels) { | ||
1470 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1471 | "CONNECT_RESP", "PLCI", cmsg->adr.adrPLCI); | ||
1472 | return; | ||
1473 | } | ||
1474 | bcs = cs->bcs + channel - 1; | ||
1475 | |||
1476 | switch (cmsg->Reject) { | ||
1477 | case 0: /* Accept */ | ||
1478 | /* drop all competing applications, keep only this one */ | ||
1479 | for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) | ||
1480 | if (oap != ap) | ||
1481 | send_disconnect_ind(bcs, oap, | ||
1482 | CapiCallGivenToOtherApplication); | ||
1483 | ap->bcnext = NULL; | ||
1484 | bcs->ap = ap; | ||
1485 | bcs->chstate |= CHS_NOTIFY_LL; | ||
1486 | |||
1487 | /* check/encode B channel protocol */ | ||
1488 | if (cmsg->BProtocol == CAPI_DEFAULT) { | ||
1489 | bcs->proto2 = L2_HDLC; | ||
1490 | dev_warn(cs->dev, | ||
1491 | "B2 Protocol X.75 SLP unsupported, using Transparent\n"); | ||
1492 | } else { | ||
1493 | switch (cmsg->B1protocol) { | ||
1494 | case 0: | ||
1495 | bcs->proto2 = L2_HDLC; | ||
1496 | break; | ||
1497 | case 1: | ||
1498 | bcs->proto2 = L2_BITSYNC; | ||
1499 | break; | ||
1500 | default: | ||
1501 | dev_warn(cs->dev, | ||
1502 | "B1 Protocol %u unsupported, using Transparent\n", | ||
1503 | cmsg->B1protocol); | ||
1504 | bcs->proto2 = L2_BITSYNC; | ||
1505 | } | ||
1506 | if (cmsg->B2protocol != 1) | ||
1507 | dev_warn(cs->dev, | ||
1508 | "B2 Protocol %u unsupported, using Transparent\n", | ||
1509 | cmsg->B2protocol); | ||
1510 | if (cmsg->B3protocol != 0) | ||
1511 | dev_warn(cs->dev, | ||
1512 | "B3 Protocol %u unsupported, using Transparent\n", | ||
1513 | cmsg->B3protocol); | ||
1514 | ignore_cstruct_param(cs, cmsg->B1configuration, | ||
1515 | "CONNECT_RESP", "B1 Configuration"); | ||
1516 | ignore_cstruct_param(cs, cmsg->B2configuration, | ||
1517 | "CONNECT_RESP", "B2 Configuration"); | ||
1518 | ignore_cstruct_param(cs, cmsg->B3configuration, | ||
1519 | "CONNECT_RESP", "B3 Configuration"); | ||
1520 | } | ||
1521 | |||
1522 | /* ToDo: check/encode remaining parameters */ | ||
1523 | ignore_cstruct_param(cs, cmsg->ConnectedNumber, | ||
1524 | "CONNECT_RESP", "Connected Number"); | ||
1525 | ignore_cstruct_param(cs, cmsg->ConnectedSubaddress, | ||
1526 | "CONNECT_RESP", "Connected Subaddress"); | ||
1527 | ignore_cstruct_param(cs, cmsg->LLC, | ||
1528 | "CONNECT_RESP", "LLC"); | ||
1529 | if (cmsg->AdditionalInfo != CAPI_DEFAULT) { | ||
1530 | ignore_cstruct_param(cs, cmsg->BChannelinformation, | ||
1531 | "CONNECT_RESP", "BChannel Information"); | ||
1532 | ignore_cstruct_param(cs, cmsg->Keypadfacility, | ||
1533 | "CONNECT_RESP", "Keypad Facility"); | ||
1534 | ignore_cstruct_param(cs, cmsg->Useruserdata, | ||
1535 | "CONNECT_RESP", "User-User Data"); | ||
1536 | ignore_cstruct_param(cs, cmsg->Facilitydataarray, | ||
1537 | "CONNECT_RESP", "Facility Data Array"); | ||
1538 | } | ||
1539 | |||
1540 | /* Accept call */ | ||
1541 | if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, | ||
1542 | EV_ACCEPT, NULL, 0, NULL)) | ||
1543 | return; | ||
1544 | gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); | ||
1545 | gigaset_schedule_event(cs); | ||
1546 | return; | ||
1547 | |||
1548 | case 1: /* Ignore */ | ||
1549 | /* send DISCONNECT_IND to this application */ | ||
1550 | send_disconnect_ind(bcs, ap, 0); | ||
1551 | |||
1552 | /* remove it from the list of listening apps */ | ||
1553 | if (bcs->ap == ap) { | ||
1554 | bcs->ap = ap->bcnext; | ||
1555 | if (bcs->ap == NULL) | ||
1556 | /* last one: stop ev-layer hupD notifications */ | ||
1557 | bcs->chstate &= ~CHS_NOTIFY_LL; | ||
1558 | return; | ||
1559 | } | ||
1560 | for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) { | ||
1561 | if (oap->bcnext == ap) { | ||
1562 | oap->bcnext = oap->bcnext->bcnext; | ||
1563 | return; | ||
1564 | } | ||
1565 | } | ||
1566 | dev_err(cs->dev, "%s: application %u not found\n", | ||
1567 | __func__, ap->id); | ||
1568 | return; | ||
1569 | |||
1570 | default: /* Reject */ | ||
1571 | /* drop all competing applications, keep only this one */ | ||
1572 | for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) | ||
1573 | if (oap != ap) | ||
1574 | send_disconnect_ind(bcs, oap, | ||
1575 | CapiCallGivenToOtherApplication); | ||
1576 | ap->bcnext = NULL; | ||
1577 | bcs->ap = ap; | ||
1578 | |||
1579 | /* reject call - will trigger DISCONNECT_IND for this app */ | ||
1580 | dev_info(cs->dev, "%s: Reject=%x\n", | ||
1581 | "CONNECT_RESP", cmsg->Reject); | ||
1582 | if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, | ||
1583 | EV_HUP, NULL, 0, NULL)) | ||
1584 | return; | ||
1585 | gig_dbg(DEBUG_CMD, "scheduling HUP"); | ||
1586 | gigaset_schedule_event(cs); | ||
1587 | return; | ||
1588 | } | ||
1589 | } | ||
1590 | |||
1591 | /* | ||
1592 | * process CONNECT_B3_REQ message | ||
1593 | * build NCCI and emit CONNECT_B3_CONF reply | ||
1594 | */ | ||
1595 | static void do_connect_b3_req(struct gigaset_capi_ctr *iif, | ||
1596 | struct gigaset_capi_appl *ap, | ||
1597 | struct sk_buff *skb) | ||
1598 | { | ||
1599 | struct cardstate *cs = iif->ctr.driverdata; | ||
1600 | _cmsg *cmsg = &iif->acmsg; | ||
1601 | int channel; | ||
1602 | |||
1603 | /* decode message */ | ||
1604 | capi_message2cmsg(cmsg, skb->data); | ||
1605 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1606 | |||
1607 | /* extract and check channel number from PLCI */ | ||
1608 | channel = (cmsg->adr.adrPLCI >> 8) & 0xff; | ||
1609 | if (!channel || channel > cs->channels) { | ||
1610 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1611 | "CONNECT_B3_REQ", "PLCI", cmsg->adr.adrPLCI); | ||
1612 | send_conf(iif, ap, skb, CapiIllContrPlciNcci); | ||
1613 | return; | ||
1614 | } | ||
1615 | |||
1616 | /* mark logical connection active */ | ||
1617 | ap->connected = APCONN_ACTIVE; | ||
1618 | |||
1619 | /* build NCCI: always 1 (one B3 connection only) */ | ||
1620 | cmsg->adr.adrNCCI |= 1 << 16; | ||
1621 | |||
1622 | /* NCPI parameter: not applicable for B3 Transparent */ | ||
1623 | ignore_cstruct_param(cs, cmsg->NCPI, "CONNECT_B3_REQ", "NCPI"); | ||
1624 | send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ? | ||
1625 | CapiNcpiNotSupportedByProtocol : CapiSuccess); | ||
1626 | } | ||
1627 | |||
1628 | /* | ||
1629 | * process CONNECT_B3_RESP message | ||
1630 | * Depending on the Reject parameter, either emit CONNECT_B3_ACTIVE_IND | ||
1631 | * or queue EV_HUP and emit DISCONNECT_B3_IND. | ||
1632 | * The emitted message is always shorter than the received one, | ||
1633 | * allowing to reuse the skb. | ||
1634 | */ | ||
1635 | static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, | ||
1636 | struct gigaset_capi_appl *ap, | ||
1637 | struct sk_buff *skb) | ||
1638 | { | ||
1639 | struct cardstate *cs = iif->ctr.driverdata; | ||
1640 | _cmsg *cmsg = &iif->acmsg; | ||
1641 | struct bc_state *bcs; | ||
1642 | int channel; | ||
1643 | unsigned int msgsize; | ||
1644 | u8 command; | ||
1645 | |||
1646 | /* decode message */ | ||
1647 | capi_message2cmsg(cmsg, skb->data); | ||
1648 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1649 | |||
1650 | /* extract and check channel number and NCCI */ | ||
1651 | channel = (cmsg->adr.adrNCCI >> 8) & 0xff; | ||
1652 | if (!channel || channel > cs->channels || | ||
1653 | ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { | ||
1654 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1655 | "CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI); | ||
1656 | dev_kfree_skb_any(skb); | ||
1657 | return; | ||
1658 | } | ||
1659 | bcs = &cs->bcs[channel-1]; | ||
1660 | |||
1661 | if (cmsg->Reject) { | ||
1662 | /* Reject: clear B3 connect received flag */ | ||
1663 | ap->connected = APCONN_SETUP; | ||
1664 | |||
1665 | /* trigger hangup, causing eventual DISCONNECT_IND */ | ||
1666 | if (!gigaset_add_event(cs, &bcs->at_state, | ||
1667 | EV_HUP, NULL, 0, NULL)) { | ||
1668 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1669 | dev_kfree_skb_any(skb); | ||
1670 | return; | ||
1671 | } | ||
1672 | gig_dbg(DEBUG_CMD, "scheduling HUP"); | ||
1673 | gigaset_schedule_event(cs); | ||
1674 | |||
1675 | /* emit DISCONNECT_B3_IND */ | ||
1676 | command = CAPI_DISCONNECT_B3; | ||
1677 | msgsize = CAPI_DISCONNECT_B3_IND_BASELEN; | ||
1678 | } else { | ||
1679 | /* | ||
1680 | * Accept: emit CONNECT_B3_ACTIVE_IND immediately, as | ||
1681 | * we only send CONNECT_B3_IND if the B channel is up | ||
1682 | */ | ||
1683 | command = CAPI_CONNECT_B3_ACTIVE; | ||
1684 | msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; | ||
1685 | } | ||
1686 | capi_cmsg_header(cmsg, ap->id, command, CAPI_IND, | ||
1687 | ap->nextMessageNumber++, cmsg->adr.adrNCCI); | ||
1688 | __skb_trim(skb, msgsize); | ||
1689 | capi_cmsg2message(cmsg, skb->data); | ||
1690 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1691 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
1692 | } | ||
1693 | |||
1694 | /* | ||
1695 | * process DISCONNECT_REQ message | ||
1696 | * schedule EV_HUP and emit DISCONNECT_B3_IND if necessary, | ||
1697 | * emit DISCONNECT_CONF reply | ||
1698 | */ | ||
1699 | static void do_disconnect_req(struct gigaset_capi_ctr *iif, | ||
1700 | struct gigaset_capi_appl *ap, | ||
1701 | struct sk_buff *skb) | ||
1702 | { | ||
1703 | struct cardstate *cs = iif->ctr.driverdata; | ||
1704 | _cmsg *cmsg = &iif->acmsg; | ||
1705 | struct bc_state *bcs; | ||
1706 | _cmsg *b3cmsg; | ||
1707 | struct sk_buff *b3skb; | ||
1708 | int channel; | ||
1709 | |||
1710 | /* decode message */ | ||
1711 | capi_message2cmsg(cmsg, skb->data); | ||
1712 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1713 | |||
1714 | /* extract and check channel number from PLCI */ | ||
1715 | channel = (cmsg->adr.adrPLCI >> 8) & 0xff; | ||
1716 | if (!channel || channel > cs->channels) { | ||
1717 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1718 | "DISCONNECT_REQ", "PLCI", cmsg->adr.adrPLCI); | ||
1719 | send_conf(iif, ap, skb, CapiIllContrPlciNcci); | ||
1720 | return; | ||
1721 | } | ||
1722 | bcs = cs->bcs + channel - 1; | ||
1723 | |||
1724 | /* ToDo: process parameter: Additional info */ | ||
1725 | if (cmsg->AdditionalInfo != CAPI_DEFAULT) { | ||
1726 | ignore_cstruct_param(cs, cmsg->BChannelinformation, | ||
1727 | "DISCONNECT_REQ", "B Channel Information"); | ||
1728 | ignore_cstruct_param(cs, cmsg->Keypadfacility, | ||
1729 | "DISCONNECT_REQ", "Keypad Facility"); | ||
1730 | ignore_cstruct_param(cs, cmsg->Useruserdata, | ||
1731 | "DISCONNECT_REQ", "User-User Data"); | ||
1732 | ignore_cstruct_param(cs, cmsg->Facilitydataarray, | ||
1733 | "DISCONNECT_REQ", "Facility Data Array"); | ||
1734 | } | ||
1735 | |||
1736 | /* skip if DISCONNECT_IND already sent */ | ||
1737 | if (!ap->connected) | ||
1738 | return; | ||
1739 | |||
1740 | /* check for active logical connection */ | ||
1741 | if (ap->connected >= APCONN_ACTIVE) { | ||
1742 | /* | ||
1743 | * emit DISCONNECT_B3_IND with cause 0x3301 | ||
1744 | * use separate cmsg structure, as the content of iif->acmsg | ||
1745 | * is still needed for creating the _CONF message | ||
1746 | */ | ||
1747 | b3cmsg = kmalloc(sizeof(*b3cmsg), GFP_KERNEL); | ||
1748 | if (!b3cmsg) { | ||
1749 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1750 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1751 | return; | ||
1752 | } | ||
1753 | capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, | ||
1754 | ap->nextMessageNumber++, | ||
1755 | cmsg->adr.adrPLCI | (1 << 16)); | ||
1756 | b3cmsg->Reason_B3 = CapiProtocolErrorLayer1; | ||
1757 | b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL); | ||
1758 | if (b3skb == NULL) { | ||
1759 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1760 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1761 | return; | ||
1762 | } | ||
1763 | capi_cmsg2message(b3cmsg, | ||
1764 | __skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN)); | ||
1765 | kfree(b3cmsg); | ||
1766 | capi_ctr_handle_message(&iif->ctr, ap->id, b3skb); | ||
1767 | } | ||
1768 | |||
1769 | /* trigger hangup, causing eventual DISCONNECT_IND */ | ||
1770 | if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { | ||
1771 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1772 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1773 | return; | ||
1774 | } | ||
1775 | gig_dbg(DEBUG_CMD, "scheduling HUP"); | ||
1776 | gigaset_schedule_event(cs); | ||
1777 | |||
1778 | /* emit reply */ | ||
1779 | send_conf(iif, ap, skb, CapiSuccess); | ||
1780 | } | ||
1781 | |||
1782 | /* | ||
1783 | * process DISCONNECT_B3_REQ message | ||
1784 | * schedule EV_HUP and emit DISCONNECT_B3_CONF reply | ||
1785 | */ | ||
1786 | static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, | ||
1787 | struct gigaset_capi_appl *ap, | ||
1788 | struct sk_buff *skb) | ||
1789 | { | ||
1790 | struct cardstate *cs = iif->ctr.driverdata; | ||
1791 | _cmsg *cmsg = &iif->acmsg; | ||
1792 | int channel; | ||
1793 | |||
1794 | /* decode message */ | ||
1795 | capi_message2cmsg(cmsg, skb->data); | ||
1796 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1797 | |||
1798 | /* extract and check channel number and NCCI */ | ||
1799 | channel = (cmsg->adr.adrNCCI >> 8) & 0xff; | ||
1800 | if (!channel || channel > cs->channels || | ||
1801 | ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { | ||
1802 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1803 | "DISCONNECT_B3_REQ", "NCCI", cmsg->adr.adrNCCI); | ||
1804 | send_conf(iif, ap, skb, CapiIllContrPlciNcci); | ||
1805 | return; | ||
1806 | } | ||
1807 | |||
1808 | /* reject if logical connection not active */ | ||
1809 | if (ap->connected < APCONN_ACTIVE) { | ||
1810 | send_conf(iif, ap, skb, | ||
1811 | CapiMessageNotSupportedInCurrentState); | ||
1812 | return; | ||
1813 | } | ||
1814 | |||
1815 | /* trigger hangup, causing eventual DISCONNECT_B3_IND */ | ||
1816 | if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, | ||
1817 | EV_HUP, NULL, 0, NULL)) { | ||
1818 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1819 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1820 | return; | ||
1821 | } | ||
1822 | gig_dbg(DEBUG_CMD, "scheduling HUP"); | ||
1823 | gigaset_schedule_event(cs); | ||
1824 | |||
1825 | /* NCPI parameter: not applicable for B3 Transparent */ | ||
1826 | ignore_cstruct_param(cs, cmsg->NCPI, | ||
1827 | "DISCONNECT_B3_REQ", "NCPI"); | ||
1828 | send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ? | ||
1829 | CapiNcpiNotSupportedByProtocol : CapiSuccess); | ||
1830 | } | ||
1831 | |||
1832 | /* | ||
1833 | * process DATA_B3_REQ message | ||
1834 | */ | ||
1835 | static void do_data_b3_req(struct gigaset_capi_ctr *iif, | ||
1836 | struct gigaset_capi_appl *ap, | ||
1837 | struct sk_buff *skb) | ||
1838 | { | ||
1839 | struct cardstate *cs = iif->ctr.driverdata; | ||
1840 | int channel = CAPIMSG_PLCI_PART(skb->data); | ||
1841 | u16 ncci = CAPIMSG_NCCI_PART(skb->data); | ||
1842 | u16 msglen = CAPIMSG_LEN(skb->data); | ||
1843 | u16 datalen = CAPIMSG_DATALEN(skb->data); | ||
1844 | u16 flags = CAPIMSG_FLAGS(skb->data); | ||
1845 | |||
1846 | /* frequent message, avoid _cmsg overhead */ | ||
1847 | dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data); | ||
1848 | |||
1849 | gig_dbg(DEBUG_LLDATA, | ||
1850 | "Receiving data from LL (ch: %d, flg: %x, sz: %d|%d)", | ||
1851 | channel, flags, msglen, datalen); | ||
1852 | |||
1853 | /* check parameters */ | ||
1854 | if (channel == 0 || channel > cs->channels || ncci != 1) { | ||
1855 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1856 | "DATA_B3_REQ", "NCCI", CAPIMSG_NCCI(skb->data)); | ||
1857 | send_conf(iif, ap, skb, CapiIllContrPlciNcci); | ||
1858 | return; | ||
1859 | } | ||
1860 | if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64) | ||
1861 | dev_notice(cs->dev, "%s: unexpected length %d\n", | ||
1862 | "DATA_B3_REQ", msglen); | ||
1863 | if (msglen + datalen != skb->len) | ||
1864 | dev_notice(cs->dev, "%s: length mismatch (%d+%d!=%d)\n", | ||
1865 | "DATA_B3_REQ", msglen, datalen, skb->len); | ||
1866 | if (msglen + datalen > skb->len) { | ||
1867 | /* message too short for announced data length */ | ||
1868 | send_conf(iif, ap, skb, CapiIllMessageParmCoding); /* ? */ | ||
1869 | return; | ||
1870 | } | ||
1871 | if (flags & CAPI_FLAGS_RESERVED) { | ||
1872 | dev_notice(cs->dev, "%s: reserved flags set (%x)\n", | ||
1873 | "DATA_B3_REQ", flags); | ||
1874 | send_conf(iif, ap, skb, CapiIllMessageParmCoding); | ||
1875 | return; | ||
1876 | } | ||
1877 | |||
1878 | /* reject if logical connection not active */ | ||
1879 | if (ap->connected < APCONN_ACTIVE) { | ||
1880 | send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); | ||
1881 | return; | ||
1882 | } | ||
1883 | |||
1884 | /* pull CAPI message into link layer header */ | ||
1885 | skb_reset_mac_header(skb); | ||
1886 | skb->mac_len = msglen; | ||
1887 | skb_pull(skb, msglen); | ||
1888 | |||
1889 | /* pass to device-specific module */ | ||
1890 | if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) { | ||
1891 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1892 | return; | ||
1893 | } | ||
1894 | |||
1895 | /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */ | ||
1896 | |||
1897 | /* | ||
1898 | * ToDo: honor unset "delivery confirmation" bit | ||
1899 | * (send DATA_B3_CONF immediately?) | ||
1900 | */ | ||
1901 | } | ||
1902 | |||
1903 | /* | ||
1904 | * process RESET_B3_REQ message | ||
1905 | * just always reply "not supported by current protocol" | ||
1906 | */ | ||
1907 | static void do_reset_b3_req(struct gigaset_capi_ctr *iif, | ||
1908 | struct gigaset_capi_appl *ap, | ||
1909 | struct sk_buff *skb) | ||
1910 | { | ||
1911 | /* decode message */ | ||
1912 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1913 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1914 | send_conf(iif, ap, skb, | ||
1915 | CapiResetProcedureNotSupportedByCurrentProtocol); | ||
1916 | } | ||
1917 | |||
1918 | /* | ||
1919 | * dump unsupported/ignored messages at most twice per minute, | ||
1920 | * some apps send those very frequently | ||
1921 | */ | ||
1922 | static unsigned long ignored_msg_dump_time; | ||
1923 | |||
1924 | /* | ||
1925 | * unsupported CAPI message handler | ||
1926 | */ | ||
1927 | static void do_unsupported(struct gigaset_capi_ctr *iif, | ||
1928 | struct gigaset_capi_appl *ap, | ||
1929 | struct sk_buff *skb) | ||
1930 | { | ||
1931 | /* decode message */ | ||
1932 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1933 | if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) | ||
1934 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1935 | send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); | ||
1936 | } | ||
1937 | |||
1938 | /* | ||
1939 | * CAPI message handler: no-op | ||
1940 | */ | ||
1941 | static void do_nothing(struct gigaset_capi_ctr *iif, | ||
1942 | struct gigaset_capi_appl *ap, | ||
1943 | struct sk_buff *skb) | ||
1944 | { | ||
1945 | if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) { | ||
1946 | /* decode message */ | ||
1947 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1948 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1949 | } | ||
1950 | dev_kfree_skb_any(skb); | ||
1951 | } | ||
1952 | |||
1953 | static void do_data_b3_resp(struct gigaset_capi_ctr *iif, | ||
1954 | struct gigaset_capi_appl *ap, | ||
1955 | struct sk_buff *skb) | ||
1956 | { | ||
1957 | dump_rawmsg(DEBUG_LLDATA, __func__, skb->data); | ||
1958 | dev_kfree_skb_any(skb); | ||
1959 | } | ||
1960 | |||
1961 | /* table of outgoing CAPI message handlers with lookup function */ | ||
1962 | typedef void (*capi_send_handler_t)(struct gigaset_capi_ctr *, | ||
1963 | struct gigaset_capi_appl *, | ||
1964 | struct sk_buff *); | ||
1965 | |||
1966 | static struct { | ||
1967 | u16 cmd; | ||
1968 | capi_send_handler_t handler; | ||
1969 | } capi_send_handler_table[] = { | ||
1970 | /* most frequent messages first for faster lookup */ | ||
1971 | { CAPI_DATA_B3_REQ, do_data_b3_req }, | ||
1972 | { CAPI_DATA_B3_RESP, do_data_b3_resp }, | ||
1973 | |||
1974 | { CAPI_ALERT_REQ, do_alert_req }, | ||
1975 | { CAPI_CONNECT_ACTIVE_RESP, do_nothing }, | ||
1976 | { CAPI_CONNECT_B3_ACTIVE_RESP, do_nothing }, | ||
1977 | { CAPI_CONNECT_B3_REQ, do_connect_b3_req }, | ||
1978 | { CAPI_CONNECT_B3_RESP, do_connect_b3_resp }, | ||
1979 | { CAPI_CONNECT_B3_T90_ACTIVE_RESP, do_nothing }, | ||
1980 | { CAPI_CONNECT_REQ, do_connect_req }, | ||
1981 | { CAPI_CONNECT_RESP, do_connect_resp }, | ||
1982 | { CAPI_DISCONNECT_B3_REQ, do_disconnect_b3_req }, | ||
1983 | { CAPI_DISCONNECT_B3_RESP, do_nothing }, | ||
1984 | { CAPI_DISCONNECT_REQ, do_disconnect_req }, | ||
1985 | { CAPI_DISCONNECT_RESP, do_nothing }, | ||
1986 | { CAPI_FACILITY_REQ, do_facility_req }, | ||
1987 | { CAPI_FACILITY_RESP, do_nothing }, | ||
1988 | { CAPI_LISTEN_REQ, do_listen_req }, | ||
1989 | { CAPI_SELECT_B_PROTOCOL_REQ, do_unsupported }, | ||
1990 | { CAPI_RESET_B3_REQ, do_reset_b3_req }, | ||
1991 | { CAPI_RESET_B3_RESP, do_nothing }, | ||
1992 | |||
1993 | /* | ||
1994 | * ToDo: support overlap sending (requires ev-layer state | ||
1995 | * machine extension to generate additional ATD commands) | ||
1996 | */ | ||
1997 | { CAPI_INFO_REQ, do_unsupported }, | ||
1998 | { CAPI_INFO_RESP, do_nothing }, | ||
1999 | |||
2000 | /* | ||
2001 | * ToDo: what's the proper response for these? | ||
2002 | */ | ||
2003 | { CAPI_MANUFACTURER_REQ, do_nothing }, | ||
2004 | { CAPI_MANUFACTURER_RESP, do_nothing }, | ||
2005 | }; | ||
2006 | |||
2007 | /* look up handler */ | ||
2008 | static inline capi_send_handler_t lookup_capi_send_handler(const u16 cmd) | ||
2009 | { | ||
2010 | size_t i; | ||
2011 | |||
2012 | for (i = 0; i < ARRAY_SIZE(capi_send_handler_table); i++) | ||
2013 | if (capi_send_handler_table[i].cmd == cmd) | ||
2014 | return capi_send_handler_table[i].handler; | ||
2015 | return NULL; | ||
2016 | } | ||
2017 | |||
2018 | |||
2019 | /** | ||
2020 | * gigaset_send_message() - accept a CAPI message from an application | ||
2021 | * @ctr: controller descriptor structure. | ||
2022 | * @skb: CAPI message. | ||
2023 | * | ||
2024 | * Return value: CAPI error code | ||
2025 | * Note: capidrv (and probably others, too) only uses the return value to | ||
2026 | * decide whether it has to free the skb (only if result != CAPI_NOERROR (0)) | ||
2027 | */ | ||
2028 | static u16 gigaset_send_message(struct capi_ctr *ctr, struct sk_buff *skb) | ||
2029 | { | ||
2030 | struct gigaset_capi_ctr *iif | ||
2031 | = container_of(ctr, struct gigaset_capi_ctr, ctr); | ||
2032 | struct cardstate *cs = ctr->driverdata; | ||
2033 | struct gigaset_capi_appl *ap; | ||
2034 | capi_send_handler_t handler; | ||
2035 | |||
2036 | /* can only handle linear sk_buffs */ | ||
2037 | if (skb_linearize(skb) < 0) { | ||
2038 | dev_warn(cs->dev, "%s: skb_linearize failed\n", __func__); | ||
2039 | return CAPI_MSGOSRESOURCEERR; | ||
2040 | } | ||
2041 | |||
2042 | /* retrieve application data structure */ | ||
2043 | ap = get_appl(iif, CAPIMSG_APPID(skb->data)); | ||
2044 | if (!ap) { | ||
2045 | dev_notice(cs->dev, "%s: application %u not registered\n", | ||
2046 | __func__, CAPIMSG_APPID(skb->data)); | ||
2047 | return CAPI_ILLAPPNR; | ||
2048 | } | ||
2049 | |||
2050 | /* look up command */ | ||
2051 | handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); | ||
2052 | if (!handler) { | ||
2053 | /* unknown/unsupported message type */ | ||
2054 | if (printk_ratelimit()) | ||
2055 | dev_notice(cs->dev, "%s: unsupported message %u\n", | ||
2056 | __func__, CAPIMSG_CMD(skb->data)); | ||
2057 | return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; | ||
2058 | } | ||
2059 | |||
2060 | /* serialize */ | ||
2061 | if (atomic_add_return(1, &iif->sendqlen) > 1) { | ||
2062 | /* queue behind other messages */ | ||
2063 | skb_queue_tail(&iif->sendqueue, skb); | ||
2064 | return CAPI_NOERROR; | ||
2065 | } | ||
2066 | |||
2067 | /* process message */ | ||
2068 | handler(iif, ap, skb); | ||
2069 | |||
2070 | /* process other messages arrived in the meantime */ | ||
2071 | while (atomic_sub_return(1, &iif->sendqlen) > 0) { | ||
2072 | skb = skb_dequeue(&iif->sendqueue); | ||
2073 | if (!skb) { | ||
2074 | /* should never happen */ | ||
2075 | dev_err(cs->dev, "%s: send queue empty\n", __func__); | ||
2076 | continue; | ||
2077 | } | ||
2078 | ap = get_appl(iif, CAPIMSG_APPID(skb->data)); | ||
2079 | if (!ap) { | ||
2080 | /* could that happen? */ | ||
2081 | dev_warn(cs->dev, "%s: application %u vanished\n", | ||
2082 | __func__, CAPIMSG_APPID(skb->data)); | ||
2083 | continue; | ||
2084 | } | ||
2085 | handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); | ||
2086 | if (!handler) { | ||
2087 | /* should never happen */ | ||
2088 | dev_err(cs->dev, "%s: handler %x vanished\n", | ||
2089 | __func__, CAPIMSG_CMD(skb->data)); | ||
2090 | continue; | ||
2091 | } | ||
2092 | handler(iif, ap, skb); | ||
2093 | } | ||
2094 | |||
2095 | return CAPI_NOERROR; | ||
2096 | } | ||
2097 | |||
2098 | /** | ||
2099 | * gigaset_procinfo() - build single line description for controller | ||
2100 | * @ctr: controller descriptor structure. | ||
2101 | * | ||
2102 | * Return value: pointer to generated string (null terminated) | ||
2103 | */ | ||
2104 | static char *gigaset_procinfo(struct capi_ctr *ctr) | ||
2105 | { | ||
2106 | return ctr->name; /* ToDo: more? */ | ||
2107 | } | ||
2108 | |||
2109 | /** | ||
2110 | * gigaset_ctr_read_proc() - build controller proc file entry | ||
2111 | * @page: buffer of PAGE_SIZE bytes for receiving the entry. | ||
2112 | * @start: unused. | ||
2113 | * @off: unused. | ||
2114 | * @count: unused. | ||
2115 | * @eof: unused. | ||
2116 | * @ctr: controller descriptor structure. | ||
2117 | * | ||
2118 | * Return value: length of generated entry | ||
2119 | */ | ||
2120 | static int gigaset_ctr_read_proc(char *page, char **start, off_t off, | ||
2121 | int count, int *eof, struct capi_ctr *ctr) | ||
2122 | { | ||
2123 | struct cardstate *cs = ctr->driverdata; | ||
2124 | char *s; | ||
2125 | int i; | ||
2126 | int len = 0; | ||
2127 | len += sprintf(page+len, "%-16s %s\n", "name", ctr->name); | ||
2128 | len += sprintf(page+len, "%-16s %s %s\n", "dev", | ||
2129 | dev_driver_string(cs->dev), dev_name(cs->dev)); | ||
2130 | len += sprintf(page+len, "%-16s %d\n", "id", cs->myid); | ||
2131 | if (cs->gotfwver) | ||
2132 | len += sprintf(page+len, "%-16s %d.%d.%d.%d\n", "firmware", | ||
2133 | cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]); | ||
2134 | len += sprintf(page+len, "%-16s %d\n", "channels", | ||
2135 | cs->channels); | ||
2136 | len += sprintf(page+len, "%-16s %s\n", "onechannel", | ||
2137 | cs->onechannel ? "yes" : "no"); | ||
2138 | |||
2139 | switch (cs->mode) { | ||
2140 | case M_UNKNOWN: | ||
2141 | s = "unknown"; | ||
2142 | break; | ||
2143 | case M_CONFIG: | ||
2144 | s = "config"; | ||
2145 | break; | ||
2146 | case M_UNIMODEM: | ||
2147 | s = "Unimodem"; | ||
2148 | break; | ||
2149 | case M_CID: | ||
2150 | s = "CID"; | ||
2151 | break; | ||
2152 | default: | ||
2153 | s = "??"; | ||
2154 | } | ||
2155 | len += sprintf(page+len, "%-16s %s\n", "mode", s); | ||
2156 | |||
2157 | switch (cs->mstate) { | ||
2158 | case MS_UNINITIALIZED: | ||
2159 | s = "uninitialized"; | ||
2160 | break; | ||
2161 | case MS_INIT: | ||
2162 | s = "init"; | ||
2163 | break; | ||
2164 | case MS_LOCKED: | ||
2165 | s = "locked"; | ||
2166 | break; | ||
2167 | case MS_SHUTDOWN: | ||
2168 | s = "shutdown"; | ||
2169 | break; | ||
2170 | case MS_RECOVER: | ||
2171 | s = "recover"; | ||
2172 | break; | ||
2173 | case MS_READY: | ||
2174 | s = "ready"; | ||
2175 | break; | ||
2176 | default: | ||
2177 | s = "??"; | ||
2178 | } | ||
2179 | len += sprintf(page+len, "%-16s %s\n", "mstate", s); | ||
2180 | |||
2181 | len += sprintf(page+len, "%-16s %s\n", "running", | ||
2182 | cs->running ? "yes" : "no"); | ||
2183 | len += sprintf(page+len, "%-16s %s\n", "connected", | ||
2184 | cs->connected ? "yes" : "no"); | ||
2185 | len += sprintf(page+len, "%-16s %s\n", "isdn_up", | ||
2186 | cs->isdn_up ? "yes" : "no"); | ||
2187 | len += sprintf(page+len, "%-16s %s\n", "cidmode", | ||
2188 | cs->cidmode ? "yes" : "no"); | ||
2189 | |||
2190 | for (i = 0; i < cs->channels; i++) { | ||
2191 | len += sprintf(page+len, "[%d]%-13s %d\n", i, "corrupted", | ||
2192 | cs->bcs[i].corrupted); | ||
2193 | len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_down", | ||
2194 | cs->bcs[i].trans_down); | ||
2195 | len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_up", | ||
2196 | cs->bcs[i].trans_up); | ||
2197 | len += sprintf(page+len, "[%d]%-13s %d\n", i, "chstate", | ||
2198 | cs->bcs[i].chstate); | ||
2199 | switch (cs->bcs[i].proto2) { | ||
2200 | case L2_BITSYNC: | ||
2201 | s = "bitsync"; | ||
2202 | break; | ||
2203 | case L2_HDLC: | ||
2204 | s = "HDLC"; | ||
2205 | break; | ||
2206 | case L2_VOICE: | ||
2207 | s = "voice"; | ||
2208 | break; | ||
2209 | default: | ||
2210 | s = "??"; | ||
2211 | } | ||
2212 | len += sprintf(page+len, "[%d]%-13s %s\n", i, "proto2", s); | ||
2213 | } | ||
2214 | return len; | ||
2215 | } | ||
2216 | |||
2217 | |||
2218 | static struct capi_driver capi_driver_gigaset = { | ||
2219 | .name = "gigaset", | ||
2220 | .revision = "1.0", | ||
2221 | }; | ||
2222 | |||
2223 | /** | ||
2224 | * gigaset_isdn_register() - register to LL | ||
2225 | * @cs: device descriptor structure. | ||
2226 | * @isdnid: device name. | ||
2227 | * | ||
2228 | * Called by main module to register the device with the LL. | ||
2229 | * | ||
2230 | * Return value: 1 for success, 0 for failure | ||
2231 | */ | ||
2232 | int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) | ||
2233 | { | ||
2234 | struct gigaset_capi_ctr *iif; | ||
2235 | int rc; | ||
2236 | |||
2237 | pr_info("Kernel CAPI interface\n"); | ||
2238 | |||
2239 | iif = kmalloc(sizeof(*iif), GFP_KERNEL); | ||
2240 | if (!iif) { | ||
2241 | pr_err("%s: out of memory\n", __func__); | ||
2242 | return 0; | ||
2243 | } | ||
2244 | |||
2245 | /* register driver with CAPI (ToDo: what for?) */ | ||
2246 | register_capi_driver(&capi_driver_gigaset); | ||
2247 | |||
2248 | /* prepare controller structure */ | ||
2249 | iif->ctr.owner = THIS_MODULE; | ||
2250 | iif->ctr.driverdata = cs; | ||
2251 | strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name)); | ||
2252 | iif->ctr.driver_name = "gigaset"; | ||
2253 | iif->ctr.load_firmware = gigaset_load_firmware; | ||
2254 | iif->ctr.reset_ctr = gigaset_reset_ctr; | ||
2255 | iif->ctr.register_appl = gigaset_register_appl; | ||
2256 | iif->ctr.release_appl = gigaset_release_appl; | ||
2257 | iif->ctr.send_message = gigaset_send_message; | ||
2258 | iif->ctr.procinfo = gigaset_procinfo; | ||
2259 | iif->ctr.ctr_read_proc = gigaset_ctr_read_proc; | ||
2260 | INIT_LIST_HEAD(&iif->appls); | ||
2261 | skb_queue_head_init(&iif->sendqueue); | ||
2262 | atomic_set(&iif->sendqlen, 0); | ||
2263 | |||
2264 | /* register controller with CAPI */ | ||
2265 | rc = attach_capi_ctr(&iif->ctr); | ||
2266 | if (rc) { | ||
2267 | pr_err("attach_capi_ctr failed (%d)\n", rc); | ||
2268 | unregister_capi_driver(&capi_driver_gigaset); | ||
2269 | kfree(iif); | ||
2270 | return 0; | ||
2271 | } | ||
2272 | |||
2273 | cs->iif = iif; | ||
2274 | cs->hw_hdr_len = CAPI_DATA_B3_REQ_LEN; | ||
2275 | return 1; | ||
2276 | } | ||
2277 | |||
2278 | /** | ||
2279 | * gigaset_isdn_unregister() - unregister from LL | ||
2280 | * @cs: device descriptor structure. | ||
2281 | * | ||
2282 | * Called by main module to unregister the device from the LL. | ||
2283 | */ | ||
2284 | void gigaset_isdn_unregister(struct cardstate *cs) | ||
2285 | { | ||
2286 | struct gigaset_capi_ctr *iif = cs->iif; | ||
2287 | |||
2288 | detach_capi_ctr(&iif->ctr); | ||
2289 | kfree(iif); | ||
2290 | cs->iif = NULL; | ||
2291 | unregister_capi_driver(&capi_driver_gigaset); | ||
2292 | } | ||
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 33dcd8d72b7c..c438cfcb7c6d 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -108,7 +108,7 @@ int gigaset_enterconfigmode(struct cardstate *cs) | |||
108 | { | 108 | { |
109 | int i, r; | 109 | int i, r; |
110 | 110 | ||
111 | cs->control_state = TIOCM_RTS; //FIXME | 111 | cs->control_state = TIOCM_RTS; |
112 | 112 | ||
113 | r = setflags(cs, TIOCM_DTR, 200); | 113 | r = setflags(cs, TIOCM_DTR, 200); |
114 | if (r < 0) | 114 | if (r < 0) |
@@ -132,10 +132,10 @@ int gigaset_enterconfigmode(struct cardstate *cs) | |||
132 | 132 | ||
133 | error: | 133 | error: |
134 | dev_err(cs->dev, "error %d on setuartbits\n", -r); | 134 | dev_err(cs->dev, "error %d on setuartbits\n", -r); |
135 | cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value? | 135 | cs->control_state = TIOCM_RTS|TIOCM_DTR; |
136 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); | 136 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); |
137 | 137 | ||
138 | return -1; //r | 138 | return -1; |
139 | } | 139 | } |
140 | 140 | ||
141 | static int test_timeout(struct at_state_t *at_state) | 141 | static int test_timeout(struct at_state_t *at_state) |
@@ -150,10 +150,9 @@ static int test_timeout(struct at_state_t *at_state) | |||
150 | } | 150 | } |
151 | 151 | ||
152 | if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, | 152 | if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, |
153 | at_state->timer_index, NULL)) { | 153 | at_state->timer_index, NULL)) |
154 | //FIXME what should we do? | 154 | dev_err(at_state->cs->dev, "%s: out of memory\n", |
155 | } | 155 | __func__); |
156 | |||
157 | return 1; | 156 | return 1; |
158 | } | 157 | } |
159 | 158 | ||
@@ -207,6 +206,32 @@ int gigaset_get_channel(struct bc_state *bcs) | |||
207 | return 1; | 206 | return 1; |
208 | } | 207 | } |
209 | 208 | ||
209 | struct bc_state *gigaset_get_free_channel(struct cardstate *cs) | ||
210 | { | ||
211 | unsigned long flags; | ||
212 | int i; | ||
213 | |||
214 | spin_lock_irqsave(&cs->lock, flags); | ||
215 | if (!try_module_get(cs->driver->owner)) { | ||
216 | gig_dbg(DEBUG_ANY, | ||
217 | "could not get module for allocating channel"); | ||
218 | spin_unlock_irqrestore(&cs->lock, flags); | ||
219 | return NULL; | ||
220 | } | ||
221 | for (i = 0; i < cs->channels; ++i) | ||
222 | if (!cs->bcs[i].use_count) { | ||
223 | ++cs->bcs[i].use_count; | ||
224 | cs->bcs[i].busy = 1; | ||
225 | spin_unlock_irqrestore(&cs->lock, flags); | ||
226 | gig_dbg(DEBUG_ANY, "allocated channel %d", i); | ||
227 | return cs->bcs + i; | ||
228 | } | ||
229 | module_put(cs->driver->owner); | ||
230 | spin_unlock_irqrestore(&cs->lock, flags); | ||
231 | gig_dbg(DEBUG_ANY, "no free channel"); | ||
232 | return NULL; | ||
233 | } | ||
234 | |||
210 | void gigaset_free_channel(struct bc_state *bcs) | 235 | void gigaset_free_channel(struct bc_state *bcs) |
211 | { | 236 | { |
212 | unsigned long flags; | 237 | unsigned long flags; |
@@ -367,16 +392,15 @@ static void gigaset_freebcs(struct bc_state *bcs) | |||
367 | int i; | 392 | int i; |
368 | 393 | ||
369 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); | 394 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); |
370 | if (!bcs->cs->ops->freebcshw(bcs)) { | 395 | if (!bcs->cs->ops->freebcshw(bcs)) |
371 | gig_dbg(DEBUG_INIT, "failed"); | 396 | gig_dbg(DEBUG_INIT, "failed"); |
372 | } | ||
373 | 397 | ||
374 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); | 398 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); |
375 | clear_at_state(&bcs->at_state); | 399 | clear_at_state(&bcs->at_state); |
376 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); | 400 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); |
401 | dev_kfree_skb(bcs->skb); | ||
402 | bcs->skb = NULL; | ||
377 | 403 | ||
378 | if (bcs->skb) | ||
379 | dev_kfree_skb(bcs->skb); | ||
380 | for (i = 0; i < AT_NUM; ++i) { | 404 | for (i = 0; i < AT_NUM; ++i) { |
381 | kfree(bcs->commands[i]); | 405 | kfree(bcs->commands[i]); |
382 | bcs->commands[i] = NULL; | 406 | bcs->commands[i] = NULL; |
@@ -463,6 +487,12 @@ void gigaset_freecs(struct cardstate *cs) | |||
463 | 487 | ||
464 | switch (cs->cs_init) { | 488 | switch (cs->cs_init) { |
465 | default: | 489 | default: |
490 | /* clear B channel structures */ | ||
491 | for (i = 0; i < cs->channels; ++i) { | ||
492 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); | ||
493 | gigaset_freebcs(cs->bcs + i); | ||
494 | } | ||
495 | |||
466 | /* clear device sysfs */ | 496 | /* clear device sysfs */ |
467 | gigaset_free_dev_sysfs(cs); | 497 | gigaset_free_dev_sysfs(cs); |
468 | 498 | ||
@@ -471,28 +501,20 @@ void gigaset_freecs(struct cardstate *cs) | |||
471 | gig_dbg(DEBUG_INIT, "clearing hw"); | 501 | gig_dbg(DEBUG_INIT, "clearing hw"); |
472 | cs->ops->freecshw(cs); | 502 | cs->ops->freecshw(cs); |
473 | 503 | ||
474 | //FIXME cmdbuf | ||
475 | |||
476 | /* fall through */ | 504 | /* fall through */ |
477 | case 2: /* error in initcshw */ | 505 | case 2: /* error in initcshw */ |
478 | /* Deregister from LL */ | 506 | /* Deregister from LL */ |
479 | make_invalid(cs, VALID_ID); | 507 | make_invalid(cs, VALID_ID); |
480 | gig_dbg(DEBUG_INIT, "clearing iif"); | 508 | gigaset_isdn_unregister(cs); |
481 | gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); | ||
482 | 509 | ||
483 | /* fall through */ | 510 | /* fall through */ |
484 | case 1: /* error when regestering to LL */ | 511 | case 1: /* error when registering to LL */ |
485 | gig_dbg(DEBUG_INIT, "clearing at_state"); | 512 | gig_dbg(DEBUG_INIT, "clearing at_state"); |
486 | clear_at_state(&cs->at_state); | 513 | clear_at_state(&cs->at_state); |
487 | dealloc_at_states(cs); | 514 | dealloc_at_states(cs); |
488 | 515 | ||
489 | /* fall through */ | 516 | /* fall through */ |
490 | case 0: /* error in one call to initbcs */ | 517 | case 0: /* error in basic setup */ |
491 | for (i = 0; i < cs->channels; ++i) { | ||
492 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); | ||
493 | gigaset_freebcs(cs->bcs + i); | ||
494 | } | ||
495 | |||
496 | clear_events(cs); | 518 | clear_events(cs); |
497 | gig_dbg(DEBUG_INIT, "freeing inbuf"); | 519 | gig_dbg(DEBUG_INIT, "freeing inbuf"); |
498 | kfree(cs->inbuf); | 520 | kfree(cs->inbuf); |
@@ -534,16 +556,13 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, | |||
534 | } | 556 | } |
535 | 557 | ||
536 | 558 | ||
537 | static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, | 559 | static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs) |
538 | struct cardstate *cs, int inputstate) | ||
539 | /* inbuf->read must be allocated before! */ | 560 | /* inbuf->read must be allocated before! */ |
540 | { | 561 | { |
541 | inbuf->head = 0; | 562 | inbuf->head = 0; |
542 | inbuf->tail = 0; | 563 | inbuf->tail = 0; |
543 | inbuf->cs = cs; | 564 | inbuf->cs = cs; |
544 | inbuf->bcs = bcs; /*base driver: NULL*/ | 565 | inbuf->inputstate = INS_command; |
545 | inbuf->rcvbuf = NULL; | ||
546 | inbuf->inputstate = inputstate; | ||
547 | } | 566 | } |
548 | 567 | ||
549 | /** | 568 | /** |
@@ -599,7 +618,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
599 | { | 618 | { |
600 | int i; | 619 | int i; |
601 | 620 | ||
602 | bcs->tx_skb = NULL; //FIXME -> hw part | 621 | bcs->tx_skb = NULL; |
603 | 622 | ||
604 | skb_queue_head_init(&bcs->squeue); | 623 | skb_queue_head_init(&bcs->squeue); |
605 | 624 | ||
@@ -618,13 +637,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
618 | bcs->fcs = PPP_INITFCS; | 637 | bcs->fcs = PPP_INITFCS; |
619 | bcs->inputstate = 0; | 638 | bcs->inputstate = 0; |
620 | if (cs->ignoreframes) { | 639 | if (cs->ignoreframes) { |
621 | bcs->inputstate |= INS_skip_frame; | ||
622 | bcs->skb = NULL; | 640 | bcs->skb = NULL; |
623 | } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | 641 | } else { |
624 | skb_reserve(bcs->skb, HW_HDR_LEN); | 642 | bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); |
625 | else { | 643 | if (bcs->skb != NULL) |
626 | pr_err("out of memory\n"); | 644 | skb_reserve(bcs->skb, cs->hw_hdr_len); |
627 | bcs->inputstate |= INS_skip_frame; | 645 | else |
646 | pr_err("out of memory\n"); | ||
628 | } | 647 | } |
629 | 648 | ||
630 | bcs->channel = channel; | 649 | bcs->channel = channel; |
@@ -645,8 +664,8 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
645 | gig_dbg(DEBUG_INIT, " failed"); | 664 | gig_dbg(DEBUG_INIT, " failed"); |
646 | 665 | ||
647 | gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); | 666 | gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); |
648 | if (bcs->skb) | 667 | dev_kfree_skb(bcs->skb); |
649 | dev_kfree_skb(bcs->skb); | 668 | bcs->skb = NULL; |
650 | 669 | ||
651 | return NULL; | 670 | return NULL; |
652 | } | 671 | } |
@@ -673,12 +692,13 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
673 | int onechannel, int ignoreframes, | 692 | int onechannel, int ignoreframes, |
674 | int cidmode, const char *modulename) | 693 | int cidmode, const char *modulename) |
675 | { | 694 | { |
676 | struct cardstate *cs = NULL; | 695 | struct cardstate *cs; |
677 | unsigned long flags; | 696 | unsigned long flags; |
678 | int i; | 697 | int i; |
679 | 698 | ||
680 | gig_dbg(DEBUG_INIT, "allocating cs"); | 699 | gig_dbg(DEBUG_INIT, "allocating cs"); |
681 | if (!(cs = alloc_cs(drv))) { | 700 | cs = alloc_cs(drv); |
701 | if (!cs) { | ||
682 | pr_err("maximum number of devices exceeded\n"); | 702 | pr_err("maximum number of devices exceeded\n"); |
683 | return NULL; | 703 | return NULL; |
684 | } | 704 | } |
@@ -726,14 +746,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
726 | cs->mode = M_UNKNOWN; | 746 | cs->mode = M_UNKNOWN; |
727 | cs->mstate = MS_UNINITIALIZED; | 747 | cs->mstate = MS_UNINITIALIZED; |
728 | 748 | ||
729 | for (i = 0; i < channels; ++i) { | ||
730 | gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); | ||
731 | if (!gigaset_initbcs(cs->bcs + i, cs, i)) { | ||
732 | pr_err("could not allocate channel %d data\n", i); | ||
733 | goto error; | ||
734 | } | ||
735 | } | ||
736 | |||
737 | ++cs->cs_init; | 749 | ++cs->cs_init; |
738 | 750 | ||
739 | gig_dbg(DEBUG_INIT, "setting up at_state"); | 751 | gig_dbg(DEBUG_INIT, "setting up at_state"); |
@@ -743,10 +755,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
743 | cs->cbytes = 0; | 755 | cs->cbytes = 0; |
744 | 756 | ||
745 | gig_dbg(DEBUG_INIT, "setting up inbuf"); | 757 | gig_dbg(DEBUG_INIT, "setting up inbuf"); |
746 | if (onechannel) { //FIXME distinction necessary? | 758 | gigaset_inbuf_init(cs->inbuf, cs); |
747 | gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); | ||
748 | } else | ||
749 | gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); | ||
750 | 759 | ||
751 | cs->connected = 0; | 760 | cs->connected = 0; |
752 | cs->isdn_up = 0; | 761 | cs->isdn_up = 0; |
@@ -758,7 +767,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
758 | cs->cmdbytes = 0; | 767 | cs->cmdbytes = 0; |
759 | 768 | ||
760 | gig_dbg(DEBUG_INIT, "setting up iif"); | 769 | gig_dbg(DEBUG_INIT, "setting up iif"); |
761 | if (!gigaset_register_to_LL(cs, modulename)) { | 770 | if (!gigaset_isdn_register(cs, modulename)) { |
762 | pr_err("error registering ISDN device\n"); | 771 | pr_err("error registering ISDN device\n"); |
763 | goto error; | 772 | goto error; |
764 | } | 773 | } |
@@ -777,6 +786,15 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
777 | /* set up device sysfs */ | 786 | /* set up device sysfs */ |
778 | gigaset_init_dev_sysfs(cs); | 787 | gigaset_init_dev_sysfs(cs); |
779 | 788 | ||
789 | /* set up channel data structures */ | ||
790 | for (i = 0; i < channels; ++i) { | ||
791 | gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i); | ||
792 | if (!gigaset_initbcs(cs->bcs + i, cs, i)) { | ||
793 | pr_err("could not allocate channel %d data\n", i); | ||
794 | goto error; | ||
795 | } | ||
796 | } | ||
797 | |||
780 | spin_lock_irqsave(&cs->lock, flags); | 798 | spin_lock_irqsave(&cs->lock, flags); |
781 | cs->running = 1; | 799 | cs->running = 1; |
782 | spin_unlock_irqrestore(&cs->lock, flags); | 800 | spin_unlock_irqrestore(&cs->lock, flags); |
@@ -824,9 +842,10 @@ void gigaset_bcs_reinit(struct bc_state *bcs) | |||
824 | bcs->chstate = 0; | 842 | bcs->chstate = 0; |
825 | 843 | ||
826 | bcs->ignore = cs->ignoreframes; | 844 | bcs->ignore = cs->ignoreframes; |
827 | if (bcs->ignore) | 845 | if (bcs->ignore) { |
828 | bcs->inputstate |= INS_skip_frame; | 846 | dev_kfree_skb(bcs->skb); |
829 | 847 | bcs->skb = NULL; | |
848 | } | ||
830 | 849 | ||
831 | cs->ops->reinitbcshw(bcs); | 850 | cs->ops->reinitbcshw(bcs); |
832 | } | 851 | } |
@@ -847,8 +866,6 @@ static void cleanup_cs(struct cardstate *cs) | |||
847 | free_strings(&cs->at_state); | 866 | free_strings(&cs->at_state); |
848 | gigaset_at_init(&cs->at_state, NULL, cs, 0); | 867 | gigaset_at_init(&cs->at_state, NULL, cs, 0); |
849 | 868 | ||
850 | kfree(cs->inbuf->rcvbuf); | ||
851 | cs->inbuf->rcvbuf = NULL; | ||
852 | cs->inbuf->inputstate = INS_command; | 869 | cs->inbuf->inputstate = INS_command; |
853 | cs->inbuf->head = 0; | 870 | cs->inbuf->head = 0; |
854 | cs->inbuf->tail = 0; | 871 | cs->inbuf->tail = 0; |
@@ -911,15 +928,13 @@ int gigaset_start(struct cardstate *cs) | |||
911 | cs->ops->baud_rate(cs, B115200); | 928 | cs->ops->baud_rate(cs, B115200); |
912 | cs->ops->set_line_ctrl(cs, CS8); | 929 | cs->ops->set_line_ctrl(cs, CS8); |
913 | cs->control_state = TIOCM_DTR|TIOCM_RTS; | 930 | cs->control_state = TIOCM_DTR|TIOCM_RTS; |
914 | } else { | ||
915 | //FIXME use some saved values? | ||
916 | } | 931 | } |
917 | 932 | ||
918 | cs->waiting = 1; | 933 | cs->waiting = 1; |
919 | 934 | ||
920 | if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { | 935 | if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { |
921 | cs->waiting = 0; | 936 | cs->waiting = 0; |
922 | //FIXME what should we do? | 937 | dev_err(cs->dev, "%s: out of memory\n", __func__); |
923 | goto error; | 938 | goto error; |
924 | } | 939 | } |
925 | 940 | ||
@@ -959,7 +974,7 @@ int gigaset_shutdown(struct cardstate *cs) | |||
959 | cs->waiting = 1; | 974 | cs->waiting = 1; |
960 | 975 | ||
961 | if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { | 976 | if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { |
962 | //FIXME what should we do? | 977 | dev_err(cs->dev, "%s: out of memory\n", __func__); |
963 | goto exit; | 978 | goto exit; |
964 | } | 979 | } |
965 | 980 | ||
@@ -990,7 +1005,7 @@ void gigaset_stop(struct cardstate *cs) | |||
990 | cs->waiting = 1; | 1005 | cs->waiting = 1; |
991 | 1006 | ||
992 | if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) { | 1007 | if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) { |
993 | //FIXME what should we do? | 1008 | dev_err(cs->dev, "%s: out of memory\n", __func__); |
994 | goto exit; | 1009 | goto exit; |
995 | } | 1010 | } |
996 | 1011 | ||
diff --git a/drivers/isdn/gigaset/dummyll.c b/drivers/isdn/gigaset/dummyll.c new file mode 100644 index 000000000000..5b27c996af6d --- /dev/null +++ b/drivers/isdn/gigaset/dummyll.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Dummy LL interface for the Gigaset driver | ||
3 | * | ||
4 | * Copyright (c) 2009 by Tilman Schmidt <tilman@imap.cc>. | ||
5 | * | ||
6 | * ===================================================================== | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * ===================================================================== | ||
12 | */ | ||
13 | |||
14 | #include "gigaset.h" | ||
15 | |||
16 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | ||
17 | { | ||
18 | } | ||
19 | EXPORT_SYMBOL_GPL(gigaset_skb_sent); | ||
20 | |||
21 | void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) | ||
22 | { | ||
23 | } | ||
24 | EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); | ||
25 | |||
26 | void gigaset_isdn_rcv_err(struct bc_state *bcs) | ||
27 | { | ||
28 | } | ||
29 | EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); | ||
30 | |||
31 | int gigaset_isdn_icall(struct at_state_t *at_state) | ||
32 | { | ||
33 | return ICALL_IGNORE; | ||
34 | } | ||
35 | |||
36 | void gigaset_isdn_connD(struct bc_state *bcs) | ||
37 | { | ||
38 | } | ||
39 | |||
40 | void gigaset_isdn_hupD(struct bc_state *bcs) | ||
41 | { | ||
42 | } | ||
43 | |||
44 | void gigaset_isdn_connB(struct bc_state *bcs) | ||
45 | { | ||
46 | } | ||
47 | |||
48 | void gigaset_isdn_hupB(struct bc_state *bcs) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | void gigaset_isdn_start(struct cardstate *cs) | ||
53 | { | ||
54 | } | ||
55 | |||
56 | void gigaset_isdn_stop(struct cardstate *cs) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) | ||
61 | { | ||
62 | pr_info("no ISDN subsystem interface\n"); | ||
63 | return 1; | ||
64 | } | ||
65 | |||
66 | void gigaset_isdn_unregister(struct cardstate *cs) | ||
67 | { | ||
68 | } | ||
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index cc768caa38f5..ddeb0456d202 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c | |||
@@ -40,8 +40,8 @@ | |||
40 | 40 | ||
41 | /* Possible ASCII responses */ | 41 | /* Possible ASCII responses */ |
42 | #define RSP_OK 0 | 42 | #define RSP_OK 0 |
43 | //#define RSP_BUSY 1 | 43 | #define RSP_BUSY 1 |
44 | //#define RSP_CONNECT 2 | 44 | #define RSP_CONNECT 2 |
45 | #define RSP_ZGCI 3 | 45 | #define RSP_ZGCI 3 |
46 | #define RSP_RING 4 | 46 | #define RSP_RING 4 |
47 | #define RSP_ZAOC 5 | 47 | #define RSP_ZAOC 5 |
@@ -68,7 +68,6 @@ | |||
68 | #define RSP_ZHLC (RSP_STR + STR_ZHLC) | 68 | #define RSP_ZHLC (RSP_STR + STR_ZHLC) |
69 | #define RSP_ERROR -1 /* ERROR */ | 69 | #define RSP_ERROR -1 /* ERROR */ |
70 | #define RSP_WRONG_CID -2 /* unknown cid in cmd */ | 70 | #define RSP_WRONG_CID -2 /* unknown cid in cmd */ |
71 | //#define RSP_EMPTY -3 | ||
72 | #define RSP_UNKNOWN -4 /* unknown response */ | 71 | #define RSP_UNKNOWN -4 /* unknown response */ |
73 | #define RSP_FAIL -5 /* internal error */ | 72 | #define RSP_FAIL -5 /* internal error */ |
74 | #define RSP_INVAL -6 /* invalid response */ | 73 | #define RSP_INVAL -6 /* invalid response */ |
@@ -76,9 +75,9 @@ | |||
76 | #define RSP_NONE -19 | 75 | #define RSP_NONE -19 |
77 | #define RSP_STRING -20 | 76 | #define RSP_STRING -20 |
78 | #define RSP_NULL -21 | 77 | #define RSP_NULL -21 |
79 | //#define RSP_RETRYFAIL -22 | 78 | #define RSP_RETRYFAIL -22 |
80 | //#define RSP_RETRY -23 | 79 | #define RSP_RETRY -23 |
81 | //#define RSP_SKIP -24 | 80 | #define RSP_SKIP -24 |
82 | #define RSP_INIT -27 | 81 | #define RSP_INIT -27 |
83 | #define RSP_ANY -26 | 82 | #define RSP_ANY -26 |
84 | #define RSP_LAST -28 | 83 | #define RSP_LAST -28 |
@@ -127,7 +126,6 @@ | |||
127 | #define ACT_NOTIFY_BC_UP 39 | 126 | #define ACT_NOTIFY_BC_UP 39 |
128 | #define ACT_DIAL 40 | 127 | #define ACT_DIAL 40 |
129 | #define ACT_ACCEPT 41 | 128 | #define ACT_ACCEPT 41 |
130 | #define ACT_PROTO_L2 42 | ||
131 | #define ACT_HUP 43 | 129 | #define ACT_HUP 43 |
132 | #define ACT_IF_LOCK 44 | 130 | #define ACT_IF_LOCK 44 |
133 | #define ACT_START 45 | 131 | #define ACT_START 45 |
@@ -159,229 +157,229 @@ | |||
159 | #define SEQ_UMMODE 11 | 157 | #define SEQ_UMMODE 11 |
160 | 158 | ||
161 | 159 | ||
162 | // 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring | 160 | /* 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), |
161 | * 400: hup, 500: reset, 600: dial, 700: ring */ | ||
163 | struct reply_t gigaset_tab_nocid[] = | 162 | struct reply_t gigaset_tab_nocid[] = |
164 | { | 163 | { |
165 | /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ | 164 | /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, |
166 | 165 | * action, command */ | |
167 | /* initialize device, set cid mode if possible */ | 166 | |
168 | //{RSP_INIT, -1, -1,100, 900, 0, {ACT_TEST}}, | 167 | /* initialize device, set cid mode if possible */ |
169 | //{RSP_ERROR, 900,900, -1, 0, 0, {ACT_FAILINIT}}, | 168 | {RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} }, |
170 | //{RSP_OK, 900,900, -1, 100, INIT_TIMEOUT, | 169 | |
171 | // {ACT_TIMEOUT}}, | 170 | {EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"}, |
172 | 171 | {RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING}, | |
173 | {RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT, | 172 | "+GMR\r"}, |
174 | {ACT_TIMEOUT}}, /* wait until device is ready */ | 173 | |
175 | 174 | {EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"}, | |
176 | {EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */ | 175 | {RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"}, |
177 | {RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */ | 176 | |
178 | 177 | {EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1}, | |
179 | {EV_TIMEOUT, 101,101, -1, 102, 5, {0}, "Z\r"}, /* timeout => try once again. */ | 178 | "^SDLE=0\r"}, |
180 | {RSP_ERROR, 101,101, -1, 102, 5, {0}, "Z\r"}, /* error => try once again. */ | 179 | {RSP_OK, 108, 108, -1, 104, -1}, |
181 | 180 | {RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"}, | |
182 | {EV_TIMEOUT, 102,102, -1, 108, 5, {ACT_SETDLE1}, "^SDLE=0\r"}, /* timeout => try again in DLE mode. */ | 181 | {EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} }, |
183 | {RSP_OK, 108,108, -1, 104,-1}, | 182 | {RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} }, |
184 | {RSP_ZDLE, 104,104, 0, 103, 5, {0}, "Z\r"}, | 183 | |
185 | {EV_TIMEOUT, 104,104, -1, 0, 0, {ACT_FAILINIT}}, | 184 | {EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0, |
186 | {RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}}, | 185 | ACT_HUPMODEM, |
187 | 186 | ACT_TIMEOUT} }, | |
188 | {EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0, | 187 | {EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"}, |
189 | ACT_HUPMODEM, | 188 | |
190 | ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */ | 189 | {RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"}, |
191 | {EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"}, | 190 | {RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} }, |
192 | 191 | {RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, | |
193 | {RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */ | 192 | {EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, |
194 | {RSP_OK, 107,107, -1, 0, 0, {ACT_CONFIGMODE}}, | 193 | |
195 | {RSP_ERROR, 107,107, -1, 0, 0, {ACT_FAILINIT}}, | 194 | {RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, |
196 | {EV_TIMEOUT, 107,107, -1, 0, 0, {ACT_FAILINIT}}, | 195 | {EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, |
197 | 196 | ||
198 | {RSP_ERROR, 103,103, -1, 0, 0, {ACT_FAILINIT}}, | 197 | {RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} }, |
199 | {EV_TIMEOUT, 103,103, -1, 0, 0, {ACT_FAILINIT}}, | 198 | |
200 | 199 | {EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER, | |
201 | {RSP_STRING, 120,120, -1, 121,-1, {ACT_SETVER}}, | 200 | ACT_INIT} }, |
202 | 201 | {RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER, | |
203 | {EV_TIMEOUT, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, | 202 | ACT_INIT} }, |
204 | {RSP_ERROR, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, | 203 | {RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER, |
205 | {RSP_OK, 121,121, -1, 0, 0, {ACT_GOTVER, ACT_INIT}}, | 204 | ACT_INIT} }, |
206 | 205 | ||
207 | /* leave dle mode */ | 206 | /* leave dle mode */ |
208 | {RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, | 207 | {RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, |
209 | {RSP_OK, 201,201, -1, 202,-1}, | 208 | {RSP_OK, 201, 201, -1, 202, -1}, |
210 | {RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}}, | 209 | {RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} }, |
211 | {RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}}, | 210 | {RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} }, |
212 | {RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, | 211 | {RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, |
213 | {EV_TIMEOUT, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, | 212 | {EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, |
214 | 213 | ||
215 | /* enter dle mode */ | 214 | /* enter dle mode */ |
216 | {RSP_INIT, 0, 0,SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, | 215 | {RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, |
217 | {RSP_OK, 251,251, -1, 252,-1}, | 216 | {RSP_OK, 251, 251, -1, 252, -1}, |
218 | {RSP_ZDLE, 252,252, 1, 0, 0, {ACT_DLE1}}, | 217 | {RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} }, |
219 | {RSP_ERROR, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, | 218 | {RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, |
220 | {EV_TIMEOUT, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, | 219 | {EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, |
221 | 220 | ||
222 | /* incoming call */ | 221 | /* incoming call */ |
223 | {RSP_RING, -1, -1, -1, -1,-1, {ACT_RING}}, | 222 | {RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} }, |
224 | 223 | ||
225 | /* get cid */ | 224 | /* get cid */ |
226 | //{RSP_INIT, 0, 0,300, 901, 0, {ACT_TEST}}, | 225 | {RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, |
227 | //{RSP_ERROR, 901,901, -1, 0, 0, {ACT_FAILCID}}, | 226 | {RSP_OK, 301, 301, -1, 302, -1}, |
228 | //{RSP_OK, 901,901, -1, 301, 5, {0}, "^SGCI?\r"}, | 227 | {RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} }, |
229 | 228 | {RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} }, | |
230 | {RSP_INIT, 0, 0,SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, | 229 | {EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} }, |
231 | {RSP_OK, 301,301, -1, 302,-1}, | 230 | |
232 | {RSP_ZGCI, 302,302, -1, 0, 0, {ACT_CID}}, | 231 | /* enter cid mode */ |
233 | {RSP_ERROR, 301,349, -1, 0, 0, {ACT_FAILCID}}, | 232 | {RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, |
234 | {EV_TIMEOUT, 301,349, -1, 0, 0, {ACT_FAILCID}}, | 233 | {RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} }, |
235 | 234 | {RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, | |
236 | /* enter cid mode */ | 235 | {EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, |
237 | {RSP_INIT, 0, 0,SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, | 236 | |
238 | {RSP_OK, 150,150, -1, 0, 0, {ACT_CMODESET}}, | 237 | /* leave cid mode */ |
239 | {RSP_ERROR, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, | 238 | {RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"}, |
240 | {EV_TIMEOUT, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, | 239 | {RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} }, |
241 | 240 | {RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, | |
242 | /* leave cid mode */ | 241 | {EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, |
243 | //{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "^SGCI=0\r"}, | 242 | |
244 | {RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "Z\r"}, | 243 | /* abort getting cid */ |
245 | {RSP_OK, 160,160, -1, 0, 0, {ACT_UMODESET}}, | 244 | {RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} }, |
246 | {RSP_ERROR, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, | 245 | |
247 | {EV_TIMEOUT, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, | 246 | /* reset */ |
248 | 247 | {RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, | |
249 | /* abort getting cid */ | 248 | {RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} }, |
250 | {RSP_INIT, 0, 0,SEQ_NOCID, 0, 0, {ACT_ABORTCID}}, | 249 | {RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, |
251 | 250 | {EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, | |
252 | /* reset */ | 251 | {RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} }, |
253 | {RSP_INIT, 0, 0,SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, | 252 | |
254 | {RSP_OK, 504,504, -1, 0, 0, {ACT_SDOWN}}, | 253 | {EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} }, |
255 | {RSP_ERROR, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, | 254 | {EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} }, |
256 | {EV_TIMEOUT, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, | 255 | {EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} }, |
257 | {RSP_NODEV, 501,599, -1, 0, 0, {ACT_FAKESDOWN}}, | 256 | {EV_START, -1, -1, -1, -1, -1, {ACT_START} }, |
258 | 257 | {EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} }, | |
259 | {EV_PROC_CIDMODE,-1, -1, -1, -1,-1, {ACT_PROC_CIDMODE}}, //FIXME | 258 | {EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} }, |
260 | {EV_IF_LOCK, -1, -1, -1, -1,-1, {ACT_IF_LOCK}}, //FIXME | 259 | |
261 | {EV_IF_VER, -1, -1, -1, -1,-1, {ACT_IF_VER}}, //FIXME | 260 | /* misc. */ |
262 | {EV_START, -1, -1, -1, -1,-1, {ACT_START}}, //FIXME | 261 | {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, |
263 | {EV_STOP, -1, -1, -1, -1,-1, {ACT_STOP}}, //FIXME | 262 | {RSP_ZCFGT, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
264 | {EV_SHUTDOWN, -1, -1, -1, -1,-1, {ACT_SHUTDOWN}}, //FIXME | 263 | {RSP_ZCFG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
265 | 264 | {RSP_ZLOG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, | |
266 | /* misc. */ | 265 | {RSP_ZMWI, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
267 | {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, | 266 | {RSP_ZABINFO, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
268 | {RSP_EMPTY, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 267 | {RSP_ZSMLSTCHG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
269 | {RSP_ZCFGT, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 268 | |
270 | {RSP_ZCFG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 269 | {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, |
271 | {RSP_ZLOG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 270 | {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
272 | {RSP_ZMWI, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 271 | {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, |
273 | {RSP_ZABINFO, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 272 | {RSP_LAST} |
274 | {RSP_ZSMLSTCHG,-1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | ||
275 | |||
276 | {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, | ||
277 | {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, | ||
278 | {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, | ||
279 | {RSP_LAST} | ||
280 | }; | 273 | }; |
281 | 274 | ||
282 | // 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall | 275 | /* 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, |
276 | * 400: hup, 750: accepted icall */ | ||
283 | struct reply_t gigaset_tab_cid[] = | 277 | struct reply_t gigaset_tab_cid[] = |
284 | { | 278 | { |
285 | /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ | 279 | /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, |
286 | 280 | * action, command */ | |
287 | /* dial */ | 281 | |
288 | {EV_DIAL, -1, -1, -1, -1,-1, {ACT_DIAL}}, //FIXME | 282 | /* dial */ |
289 | {RSP_INIT, 0, 0,SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC}}, | 283 | {EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} }, |
290 | {RSP_OK, 601,601, -1, 602, 5, {ACT_CMD+AT_HLC}}, | 284 | {RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} }, |
291 | {RSP_NULL, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, | 285 | {RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} }, |
292 | {RSP_OK, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, | 286 | {RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, |
293 | {RSP_OK, 603,603, -1, 604, 5, {ACT_CMD+AT_TYPE}}, | 287 | {RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, |
294 | {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, | 288 | {RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} }, |
295 | {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, | 289 | {RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} }, |
296 | {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, | 290 | {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, |
297 | {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, | 291 | {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, |
298 | {RSP_OK, 607,607, -1, 608,-1}, | 292 | {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, |
299 | {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, | 293 | {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, |
300 | {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, | 294 | {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, |
301 | 295 | {RSP_OK, 608, 608, -1, 609, -1}, | |
302 | {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, | 296 | {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD+AT_DIAL} }, |
303 | {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, | 297 | {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, |
304 | 298 | ||
305 | /* optional dialing responses */ | 299 | {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, |
306 | {EV_BC_OPEN, 650,650, -1, 651,-1}, | 300 | {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, |
307 | {RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}}, | 301 | |
308 | {RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}}, | 302 | /* optional dialing responses */ |
309 | {RSP_ZCPN, 609,651, -1, -1,-1, {ACT_DEBUG}}, | 303 | {EV_BC_OPEN, 650, 650, -1, 651, -1}, |
310 | {RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, | 304 | {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, |
311 | 305 | {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, | |
312 | /* connect */ | 306 | {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, |
313 | {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, | 307 | {RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} }, |
314 | {RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, | 308 | |
315 | ACT_NOTIFY_BC_UP}}, | 309 | /* connect */ |
316 | {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, | 310 | {RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, |
317 | {RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, | 311 | {RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, |
318 | ACT_NOTIFY_BC_UP}}, | 312 | ACT_NOTIFY_BC_UP} }, |
319 | {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, | 313 | {RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, |
320 | 314 | {RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, | |
321 | /* remote hangup */ | 315 | ACT_NOTIFY_BC_UP} }, |
322 | {RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, | 316 | {EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} }, |
323 | {RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, | 317 | |
324 | {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, | 318 | /* remote hangup */ |
325 | 319 | {RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} }, | |
326 | /* hangup */ | 320 | {RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, |
327 | {EV_HUP, -1, -1, -1, -1,-1, {ACT_HUP}}, //FIXME | 321 | {RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, |
328 | {RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1? | 322 | |
329 | {RSP_OK, 401,401, -1, 402, 5}, | 323 | /* hangup */ |
330 | {RSP_ZVLS, 402,402, 0, 403, 5}, | 324 | {EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} }, |
331 | {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, | 325 | {RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, |
332 | {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, | 326 | {RSP_OK, 401, 401, -1, 402, 5}, |
333 | {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, | 327 | {RSP_ZVLS, 402, 402, 0, 403, 5}, |
334 | {RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}}, | 328 | {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, |
335 | {EV_TIMEOUT, 401,403, -1, 0, 0, {ACT_ABORTHUP}}, | 329 | {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, |
336 | 330 | {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, | |
337 | {EV_BC_CLOSED, 0, 0, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME new constate + timeout | 331 | {RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} }, |
338 | 332 | {EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} }, | |
339 | /* ring */ | 333 | |
340 | {RSP_ZBC, 700,700, -1, -1,-1, {0}}, | 334 | {EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, |
341 | {RSP_ZHLC, 700,700, -1, -1,-1, {0}}, | 335 | |
342 | {RSP_NMBR, 700,700, -1, -1,-1, {0}}, | 336 | /* ring */ |
343 | {RSP_ZCPN, 700,700, -1, -1,-1, {0}}, | 337 | {RSP_ZBC, 700, 700, -1, -1, -1, {0} }, |
344 | {RSP_ZCTP, 700,700, -1, -1,-1, {0}}, | 338 | {RSP_ZHLC, 700, 700, -1, -1, -1, {0} }, |
345 | {EV_TIMEOUT, 700,700, -1, 720,720, {ACT_ICALL}}, | 339 | {RSP_NMBR, 700, 700, -1, -1, -1, {0} }, |
346 | {EV_BC_CLOSED,720,720, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, | 340 | {RSP_ZCPN, 700, 700, -1, -1, -1, {0} }, |
347 | 341 | {RSP_ZCTP, 700, 700, -1, -1, -1, {0} }, | |
348 | /*accept icall*/ | 342 | {EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} }, |
349 | {EV_ACCEPT, -1, -1, -1, -1,-1, {ACT_ACCEPT}}, //FIXME | 343 | {EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, |
350 | {RSP_INIT, 720,720,SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO}}, | 344 | |
351 | {RSP_OK, 721,721, -1, 722, 5, {ACT_CMD+AT_ISO}}, | 345 | /*accept icall*/ |
352 | {RSP_OK, 722,722, -1, 723, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ | 346 | {EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} }, |
353 | {RSP_OK, 723,723, -1, 724, 5, {0}}, | 347 | {RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO} }, |
354 | {RSP_ZVLS, 724,724, 17, 750,50, {ACT_ACCEPTED}}, | 348 | {RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD+AT_ISO} }, |
355 | {RSP_ERROR, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, | 349 | {RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"}, |
356 | {EV_TIMEOUT, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, | 350 | {RSP_OK, 723, 723, -1, 724, 5, {0} }, |
357 | {RSP_ZSAU, 700,729,ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT}}, | 351 | {RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} }, |
358 | {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, | 352 | {RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, |
359 | {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, | 353 | {EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, |
360 | 354 | {RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} }, | |
361 | {EV_BC_OPEN, 750,750, -1, 751,-1}, | 355 | {RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} }, |
362 | {EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}}, | 356 | {RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} }, |
363 | 357 | ||
364 | /* B channel closed (general case) */ | 358 | {EV_BC_OPEN, 750, 750, -1, 751, -1}, |
365 | {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME | 359 | {EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} }, |
366 | 360 | ||
367 | /* misc. */ | 361 | /* B channel closed (general case) */ |
368 | {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME | 362 | {EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} }, |
369 | 363 | ||
370 | {RSP_ZCON, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 364 | /* misc. */ |
371 | {RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 365 | {RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
372 | {RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 366 | {RSP_ZCCR, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
373 | {RSP_ZCSTR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 367 | {RSP_ZAOC, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
374 | 368 | {RSP_ZCSTR, -1, -1, -1, -1, -1, {ACT_DEBUG} }, | |
375 | {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, | 369 | |
376 | {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, | 370 | {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, |
377 | {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, | 371 | {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
378 | {RSP_LAST} | 372 | {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, |
373 | {RSP_LAST} | ||
379 | }; | 374 | }; |
380 | 375 | ||
381 | 376 | ||
382 | static const struct resp_type_t resp_type[] = | 377 | static const struct resp_type_t { |
378 | unsigned char *response; | ||
379 | int resp_code; | ||
380 | int type; | ||
381 | } resp_type[] = | ||
383 | { | 382 | { |
384 | /*{"", RSP_EMPTY, RT_NOTHING},*/ | ||
385 | {"OK", RSP_OK, RT_NOTHING}, | 383 | {"OK", RSP_OK, RT_NOTHING}, |
386 | {"ERROR", RSP_ERROR, RT_NOTHING}, | 384 | {"ERROR", RSP_ERROR, RT_NOTHING}, |
387 | {"ZSAU", RSP_ZSAU, RT_ZSAU}, | 385 | {"ZSAU", RSP_ZSAU, RT_ZSAU}, |
@@ -405,7 +403,21 @@ static const struct resp_type_t resp_type[] = | |||
405 | {"ZLOG", RSP_ZLOG, RT_NOTHING}, | 403 | {"ZLOG", RSP_ZLOG, RT_NOTHING}, |
406 | {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, | 404 | {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, |
407 | {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, | 405 | {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, |
408 | {NULL,0,0} | 406 | {NULL, 0, 0} |
407 | }; | ||
408 | |||
409 | static const struct zsau_resp_t { | ||
410 | unsigned char *str; | ||
411 | int code; | ||
412 | } zsau_resp[] = | ||
413 | { | ||
414 | {"OUTGOING_CALL_PROCEEDING", ZSAU_OUTGOING_CALL_PROCEEDING}, | ||
415 | {"CALL_DELIVERED", ZSAU_CALL_DELIVERED}, | ||
416 | {"ACTIVE", ZSAU_ACTIVE}, | ||
417 | {"DISCONNECT_IND", ZSAU_DISCONNECT_IND}, | ||
418 | {"NULL", ZSAU_NULL}, | ||
419 | {"DISCONNECT_REQ", ZSAU_DISCONNECT_REQ}, | ||
420 | {NULL, ZSAU_UNKNOWN} | ||
409 | }; | 421 | }; |
410 | 422 | ||
411 | /* | 423 | /* |
@@ -470,7 +482,6 @@ static int cid_of_response(char *s) | |||
470 | if (cid < 1 || cid > 65535) | 482 | if (cid < 1 || cid > 65535) |
471 | return -1; /* CID out of range */ | 483 | return -1; /* CID out of range */ |
472 | return cid; | 484 | return cid; |
473 | //FIXME is ;<digit>+ at end of non-CID response really impossible? | ||
474 | } | 485 | } |
475 | 486 | ||
476 | /** | 487 | /** |
@@ -487,6 +498,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) | |||
487 | int params; | 498 | int params; |
488 | int i, j; | 499 | int i, j; |
489 | const struct resp_type_t *rt; | 500 | const struct resp_type_t *rt; |
501 | const struct zsau_resp_t *zr; | ||
490 | int curarg; | 502 | int curarg; |
491 | unsigned long flags; | 503 | unsigned long flags; |
492 | unsigned next, tail, head; | 504 | unsigned next, tail, head; |
@@ -613,24 +625,14 @@ void gigaset_handle_modem_response(struct cardstate *cs) | |||
613 | event->parameter = ZSAU_NONE; | 625 | event->parameter = ZSAU_NONE; |
614 | break; | 626 | break; |
615 | } | 627 | } |
616 | if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING")) | 628 | for (zr = zsau_resp; zr->str; ++zr) |
617 | event->parameter = ZSAU_OUTGOING_CALL_PROCEEDING; | 629 | if (!strcmp(argv[curarg], zr->str)) |
618 | else if (!strcmp(argv[curarg], "CALL_DELIVERED")) | 630 | break; |
619 | event->parameter = ZSAU_CALL_DELIVERED; | 631 | event->parameter = zr->code; |
620 | else if (!strcmp(argv[curarg], "ACTIVE")) | 632 | if (!zr->str) |
621 | event->parameter = ZSAU_ACTIVE; | ||
622 | else if (!strcmp(argv[curarg], "DISCONNECT_IND")) | ||
623 | event->parameter = ZSAU_DISCONNECT_IND; | ||
624 | else if (!strcmp(argv[curarg], "NULL")) | ||
625 | event->parameter = ZSAU_NULL; | ||
626 | else if (!strcmp(argv[curarg], "DISCONNECT_REQ")) | ||
627 | event->parameter = ZSAU_DISCONNECT_REQ; | ||
628 | else { | ||
629 | event->parameter = ZSAU_UNKNOWN; | ||
630 | dev_warn(cs->dev, | 633 | dev_warn(cs->dev, |
631 | "%s: unknown parameter %s after ZSAU\n", | 634 | "%s: unknown parameter %s after ZSAU\n", |
632 | __func__, argv[curarg]); | 635 | __func__, argv[curarg]); |
633 | } | ||
634 | ++curarg; | 636 | ++curarg; |
635 | break; | 637 | break; |
636 | case RT_STRING: | 638 | case RT_STRING: |
@@ -714,7 +716,7 @@ static void disconnect(struct at_state_t **at_state_p) | |||
714 | /* notify LL */ | 716 | /* notify LL */ |
715 | if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { | 717 | if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { |
716 | bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); | 718 | bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); |
717 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); | 719 | gigaset_isdn_hupD(bcs); |
718 | } | 720 | } |
719 | } else { | 721 | } else { |
720 | /* no B channel assigned: just deallocate */ | 722 | /* no B channel assigned: just deallocate */ |
@@ -872,12 +874,12 @@ static void bchannel_down(struct bc_state *bcs) | |||
872 | { | 874 | { |
873 | if (bcs->chstate & CHS_B_UP) { | 875 | if (bcs->chstate & CHS_B_UP) { |
874 | bcs->chstate &= ~CHS_B_UP; | 876 | bcs->chstate &= ~CHS_B_UP; |
875 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); | 877 | gigaset_isdn_hupB(bcs); |
876 | } | 878 | } |
877 | 879 | ||
878 | if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { | 880 | if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { |
879 | bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); | 881 | bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); |
880 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); | 882 | gigaset_isdn_hupD(bcs); |
881 | } | 883 | } |
882 | 884 | ||
883 | gigaset_free_channel(bcs); | 885 | gigaset_free_channel(bcs); |
@@ -894,15 +896,17 @@ static void bchannel_up(struct bc_state *bcs) | |||
894 | } | 896 | } |
895 | 897 | ||
896 | bcs->chstate |= CHS_B_UP; | 898 | bcs->chstate |= CHS_B_UP; |
897 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); | 899 | gigaset_isdn_connB(bcs); |
898 | } | 900 | } |
899 | 901 | ||
900 | static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index) | 902 | static void start_dial(struct at_state_t *at_state, void *data, |
903 | unsigned seq_index) | ||
901 | { | 904 | { |
902 | struct bc_state *bcs = at_state->bcs; | 905 | struct bc_state *bcs = at_state->bcs; |
903 | struct cardstate *cs = at_state->cs; | 906 | struct cardstate *cs = at_state->cs; |
904 | int retval; | 907 | char **commands = data; |
905 | unsigned long flags; | 908 | unsigned long flags; |
909 | int i; | ||
906 | 910 | ||
907 | bcs->chstate |= CHS_NOTIFY_LL; | 911 | bcs->chstate |= CHS_NOTIFY_LL; |
908 | 912 | ||
@@ -913,10 +917,10 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind | |||
913 | } | 917 | } |
914 | spin_unlock_irqrestore(&cs->lock, flags); | 918 | spin_unlock_irqrestore(&cs->lock, flags); |
915 | 919 | ||
916 | retval = gigaset_isdn_setup_dial(at_state, data); | 920 | for (i = 0; i < AT_NUM; ++i) { |
917 | if (retval != 0) | 921 | kfree(bcs->commands[i]); |
918 | goto error; | 922 | bcs->commands[i] = commands[i]; |
919 | 923 | } | |
920 | 924 | ||
921 | at_state->pending_commands |= PC_CID; | 925 | at_state->pending_commands |= PC_CID; |
922 | gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); | 926 | gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); |
@@ -924,6 +928,10 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind | |||
924 | return; | 928 | return; |
925 | 929 | ||
926 | error: | 930 | error: |
931 | for (i = 0; i < AT_NUM; ++i) { | ||
932 | kfree(commands[i]); | ||
933 | commands[i] = NULL; | ||
934 | } | ||
927 | at_state->pending_commands |= PC_NOCID; | 935 | at_state->pending_commands |= PC_NOCID; |
928 | gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); | 936 | gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); |
929 | cs->commands_pending = 1; | 937 | cs->commands_pending = 1; |
@@ -933,20 +941,31 @@ error: | |||
933 | static void start_accept(struct at_state_t *at_state) | 941 | static void start_accept(struct at_state_t *at_state) |
934 | { | 942 | { |
935 | struct cardstate *cs = at_state->cs; | 943 | struct cardstate *cs = at_state->cs; |
936 | int retval; | 944 | struct bc_state *bcs = at_state->bcs; |
945 | int i; | ||
937 | 946 | ||
938 | retval = gigaset_isdn_setup_accept(at_state); | 947 | for (i = 0; i < AT_NUM; ++i) { |
948 | kfree(bcs->commands[i]); | ||
949 | bcs->commands[i] = NULL; | ||
950 | } | ||
939 | 951 | ||
940 | if (retval == 0) { | 952 | bcs->commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); |
941 | at_state->pending_commands |= PC_ACCEPT; | 953 | bcs->commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); |
942 | gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); | 954 | if (!bcs->commands[AT_PROTO] || !bcs->commands[AT_ISO]) { |
943 | cs->commands_pending = 1; | 955 | dev_err(at_state->cs->dev, "out of memory\n"); |
944 | } else { | ||
945 | /* error reset */ | 956 | /* error reset */ |
946 | at_state->pending_commands |= PC_HUP; | 957 | at_state->pending_commands |= PC_HUP; |
947 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); | 958 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); |
948 | cs->commands_pending = 1; | 959 | cs->commands_pending = 1; |
960 | return; | ||
949 | } | 961 | } |
962 | |||
963 | snprintf(bcs->commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); | ||
964 | snprintf(bcs->commands[AT_ISO], 9, "^SISO=%u\r", bcs->channel + 1); | ||
965 | |||
966 | at_state->pending_commands |= PC_ACCEPT; | ||
967 | gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); | ||
968 | cs->commands_pending = 1; | ||
950 | } | 969 | } |
951 | 970 | ||
952 | static void do_start(struct cardstate *cs) | 971 | static void do_start(struct cardstate *cs) |
@@ -957,9 +976,7 @@ static void do_start(struct cardstate *cs) | |||
957 | schedule_init(cs, MS_INIT); | 976 | schedule_init(cs, MS_INIT); |
958 | 977 | ||
959 | cs->isdn_up = 1; | 978 | cs->isdn_up = 1; |
960 | gigaset_i4l_cmd(cs, ISDN_STAT_RUN); | 979 | gigaset_isdn_start(cs); |
961 | // FIXME: not in locked mode | ||
962 | // FIXME 2: only after init sequence | ||
963 | 980 | ||
964 | cs->waiting = 0; | 981 | cs->waiting = 0; |
965 | wake_up(&cs->waitqueue); | 982 | wake_up(&cs->waitqueue); |
@@ -975,7 +992,7 @@ static void finish_shutdown(struct cardstate *cs) | |||
975 | /* Tell the LL that the device is not available .. */ | 992 | /* Tell the LL that the device is not available .. */ |
976 | if (cs->isdn_up) { | 993 | if (cs->isdn_up) { |
977 | cs->isdn_up = 0; | 994 | cs->isdn_up = 0; |
978 | gigaset_i4l_cmd(cs, ISDN_STAT_STOP); | 995 | gigaset_isdn_stop(cs); |
979 | } | 996 | } |
980 | 997 | ||
981 | /* The rest is done by cleanup_cs () in user mode. */ | 998 | /* The rest is done by cleanup_cs () in user mode. */ |
@@ -1113,7 +1130,6 @@ static int do_lock(struct cardstate *cs) | |||
1113 | 1130 | ||
1114 | break; | 1131 | break; |
1115 | case MS_LOCKED: | 1132 | case MS_LOCKED: |
1116 | //retval = -EACCES; | ||
1117 | break; | 1133 | break; |
1118 | default: | 1134 | default: |
1119 | return -EBUSY; | 1135 | return -EBUSY; |
@@ -1276,7 +1292,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1276 | break; | 1292 | break; |
1277 | } | 1293 | } |
1278 | bcs->chstate |= CHS_D_UP; | 1294 | bcs->chstate |= CHS_D_UP; |
1279 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); | 1295 | gigaset_isdn_connD(bcs); |
1280 | cs->ops->init_bchannel(bcs); | 1296 | cs->ops->init_bchannel(bcs); |
1281 | break; | 1297 | break; |
1282 | case ACT_DLE1: | 1298 | case ACT_DLE1: |
@@ -1284,7 +1300,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1284 | bcs = cs->bcs + cs->curchannel; | 1300 | bcs = cs->bcs + cs->curchannel; |
1285 | 1301 | ||
1286 | bcs->chstate |= CHS_D_UP; | 1302 | bcs->chstate |= CHS_D_UP; |
1287 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); | 1303 | gigaset_isdn_connD(bcs); |
1288 | cs->ops->init_bchannel(bcs); | 1304 | cs->ops->init_bchannel(bcs); |
1289 | break; | 1305 | break; |
1290 | case ACT_FAKEHUP: | 1306 | case ACT_FAKEHUP: |
@@ -1369,7 +1385,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1369 | cs->cur_at_seq = SEQ_NONE; | 1385 | cs->cur_at_seq = SEQ_NONE; |
1370 | break; | 1386 | break; |
1371 | 1387 | ||
1372 | case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */ | 1388 | case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL procssng */ |
1373 | disconnect(p_at_state); | 1389 | disconnect(p_at_state); |
1374 | break; | 1390 | break; |
1375 | 1391 | ||
@@ -1443,17 +1459,6 @@ static void do_action(int action, struct cardstate *cs, | |||
1443 | __func__, at_state->ConState); | 1459 | __func__, at_state->ConState); |
1444 | cs->cur_at_seq = SEQ_NONE; | 1460 | cs->cur_at_seq = SEQ_NONE; |
1445 | break; | 1461 | break; |
1446 | #ifdef CONFIG_GIGASET_DEBUG | ||
1447 | case ACT_TEST: | ||
1448 | { | ||
1449 | static int count = 3; //2; //1; | ||
1450 | *p_genresp = 1; | ||
1451 | *p_resp_code = count ? RSP_ERROR : RSP_OK; | ||
1452 | if (count > 0) | ||
1453 | --count; | ||
1454 | } | ||
1455 | break; | ||
1456 | #endif | ||
1457 | case ACT_DEBUG: | 1462 | case ACT_DEBUG: |
1458 | gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", | 1463 | gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", |
1459 | __func__, ev->type, at_state->ConState); | 1464 | __func__, ev->type, at_state->ConState); |
@@ -1474,11 +1479,6 @@ static void do_action(int action, struct cardstate *cs, | |||
1474 | case ACT_ACCEPT: | 1479 | case ACT_ACCEPT: |
1475 | start_accept(at_state); | 1480 | start_accept(at_state); |
1476 | break; | 1481 | break; |
1477 | case ACT_PROTO_L2: | ||
1478 | gig_dbg(DEBUG_CMD, "set protocol to %u", | ||
1479 | (unsigned) ev->parameter); | ||
1480 | at_state->bcs->proto2 = ev->parameter; | ||
1481 | break; | ||
1482 | case ACT_HUP: | 1482 | case ACT_HUP: |
1483 | at_state->pending_commands |= PC_HUP; | 1483 | at_state->pending_commands |= PC_HUP; |
1484 | cs->commands_pending = 1; | 1484 | cs->commands_pending = 1; |
@@ -1493,7 +1493,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1493 | do_start(cs); | 1493 | do_start(cs); |
1494 | break; | 1494 | break; |
1495 | 1495 | ||
1496 | /* events from the interface */ // FIXME without ACT_xxxx? | 1496 | /* events from the interface */ |
1497 | case ACT_IF_LOCK: | 1497 | case ACT_IF_LOCK: |
1498 | cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); | 1498 | cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); |
1499 | cs->waiting = 0; | 1499 | cs->waiting = 0; |
@@ -1512,7 +1512,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1512 | wake_up(&cs->waitqueue); | 1512 | wake_up(&cs->waitqueue); |
1513 | break; | 1513 | break; |
1514 | 1514 | ||
1515 | /* events from the proc file system */ // FIXME without ACT_xxxx? | 1515 | /* events from the proc file system */ |
1516 | case ACT_PROC_CIDMODE: | 1516 | case ACT_PROC_CIDMODE: |
1517 | spin_lock_irqsave(&cs->lock, flags); | 1517 | spin_lock_irqsave(&cs->lock, flags); |
1518 | if (ev->parameter != cs->cidmode) { | 1518 | if (ev->parameter != cs->cidmode) { |
@@ -1649,7 +1649,8 @@ static void process_event(struct cardstate *cs, struct event_t *ev) | |||
1649 | for (curact = 0; curact < MAXACT; ++curact) { | 1649 | for (curact = 0; curact < MAXACT; ++curact) { |
1650 | /* The row tells us what we should do .. | 1650 | /* The row tells us what we should do .. |
1651 | */ | 1651 | */ |
1652 | do_action(rep->action[curact], cs, bcs, &at_state, &p_command, &genresp, &resp_code, ev); | 1652 | do_action(rep->action[curact], cs, bcs, &at_state, &p_command, |
1653 | &genresp, &resp_code, ev); | ||
1653 | if (!at_state) | 1654 | if (!at_state) |
1654 | break; /* may be freed after disconnect */ | 1655 | break; /* may be freed after disconnect */ |
1655 | } | 1656 | } |
@@ -1661,13 +1662,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev) | |||
1661 | 1662 | ||
1662 | if (genresp) { | 1663 | if (genresp) { |
1663 | spin_lock_irqsave(&cs->lock, flags); | 1664 | spin_lock_irqsave(&cs->lock, flags); |
1664 | at_state->timer_expires = 0; //FIXME | 1665 | at_state->timer_expires = 0; |
1665 | at_state->timer_active = 0; //FIXME | 1666 | at_state->timer_active = 0; |
1666 | spin_unlock_irqrestore(&cs->lock, flags); | 1667 | spin_unlock_irqrestore(&cs->lock, flags); |
1667 | gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL); | 1668 | gigaset_add_event(cs, at_state, resp_code, |
1669 | NULL, 0, NULL); | ||
1668 | } else { | 1670 | } else { |
1669 | /* Send command to modem if not NULL... */ | 1671 | /* Send command to modem if not NULL... */ |
1670 | if (p_command/*rep->command*/) { | 1672 | if (p_command) { |
1671 | if (cs->connected) | 1673 | if (cs->connected) |
1672 | send_command(cs, p_command, | 1674 | send_command(cs, p_command, |
1673 | sendcid, cs->dle, | 1675 | sendcid, cs->dle, |
@@ -1754,7 +1756,8 @@ static void process_command_flags(struct cardstate *cs) | |||
1754 | } | 1756 | } |
1755 | } | 1757 | } |
1756 | 1758 | ||
1757 | /* only switch back to unimodem mode, if no commands are pending and no channels are up */ | 1759 | /* only switch back to unimodem mode if no commands are pending and |
1760 | * no channels are up */ | ||
1758 | spin_lock_irqsave(&cs->lock, flags); | 1761 | spin_lock_irqsave(&cs->lock, flags); |
1759 | if (cs->at_state.pending_commands == PC_UMMODE | 1762 | if (cs->at_state.pending_commands == PC_UMMODE |
1760 | && !cs->cidmode | 1763 | && !cs->cidmode |
@@ -1813,9 +1816,8 @@ static void process_command_flags(struct cardstate *cs) | |||
1813 | 1816 | ||
1814 | if (cs->at_state.pending_commands & PC_INIT) { | 1817 | if (cs->at_state.pending_commands & PC_INIT) { |
1815 | cs->at_state.pending_commands &= ~PC_INIT; | 1818 | cs->at_state.pending_commands &= ~PC_INIT; |
1816 | cs->dle = 0; //FIXME | 1819 | cs->dle = 0; |
1817 | cs->inbuf->inputstate = INS_command; | 1820 | cs->inbuf->inputstate = INS_command; |
1818 | //FIXME reset card state (or -> LOCK0)? | ||
1819 | schedule_sequence(cs, &cs->at_state, SEQ_INIT); | 1821 | schedule_sequence(cs, &cs->at_state, SEQ_INIT); |
1820 | return; | 1822 | return; |
1821 | } | 1823 | } |
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index a2f6125739eb..e963a6c2e86d 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/compiler.h> | 23 | #include <linux/compiler.h> |
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include <linux/isdnif.h> | ||
27 | #include <linux/usb.h> | 26 | #include <linux/usb.h> |
28 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
29 | #include <linux/netdevice.h> | 28 | #include <linux/netdevice.h> |
@@ -35,12 +34,11 @@ | |||
35 | #include <linux/list.h> | 34 | #include <linux/list.h> |
36 | #include <asm/atomic.h> | 35 | #include <asm/atomic.h> |
37 | 36 | ||
38 | #define GIG_VERSION {0,5,0,0} | 37 | #define GIG_VERSION {0, 5, 0, 0} |
39 | #define GIG_COMPAT {0,4,0,0} | 38 | #define GIG_COMPAT {0, 4, 0, 0} |
40 | 39 | ||
41 | #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ | 40 | #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ |
42 | #define MAX_RESP_SIZE 512 /* Max. size of a response string */ | 41 | #define MAX_RESP_SIZE 512 /* Max. size of a response string */ |
43 | #define HW_HDR_LEN 2 /* Header size used to store ack info */ | ||
44 | 42 | ||
45 | #define MAX_EVENTS 64 /* size of event queue */ | 43 | #define MAX_EVENTS 64 /* size of event queue */ |
46 | 44 | ||
@@ -135,35 +133,32 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
135 | #define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) | 133 | #define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) |
136 | #define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) | 134 | #define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) |
137 | 135 | ||
138 | /* int-in-events 3070 */ | 136 | /* interrupt pipe messages */ |
139 | #define HD_B1_FLOW_CONTROL 0x80 | 137 | #define HD_B1_FLOW_CONTROL 0x80 |
140 | #define HD_B2_FLOW_CONTROL 0x81 | 138 | #define HD_B2_FLOW_CONTROL 0x81 |
141 | #define HD_RECEIVEATDATA_ACK (0x35) // 3070 | 139 | #define HD_RECEIVEATDATA_ACK (0x35) /* 3070 */ |
142 | // att: HD_RECEIVE>>AT<<DATA_ACK | 140 | #define HD_READY_SEND_ATDATA (0x36) /* 3070 */ |
143 | #define HD_READY_SEND_ATDATA (0x36) // 3070 | 141 | #define HD_OPEN_ATCHANNEL_ACK (0x37) /* 3070 */ |
144 | #define HD_OPEN_ATCHANNEL_ACK (0x37) // 3070 | 142 | #define HD_CLOSE_ATCHANNEL_ACK (0x38) /* 3070 */ |
145 | #define HD_CLOSE_ATCHANNEL_ACK (0x38) // 3070 | 143 | #define HD_DEVICE_INIT_OK (0x11) /* ISurf USB + 3070 */ |
146 | #define HD_DEVICE_INIT_OK (0x11) // ISurf USB + 3070 | 144 | #define HD_OPEN_B1CHANNEL_ACK (0x51) /* ISurf USB + 3070 */ |
147 | #define HD_OPEN_B1CHANNEL_ACK (0x51) // ISurf USB + 3070 | 145 | #define HD_OPEN_B2CHANNEL_ACK (0x52) /* ISurf USB + 3070 */ |
148 | #define HD_OPEN_B2CHANNEL_ACK (0x52) // ISurf USB + 3070 | 146 | #define HD_CLOSE_B1CHANNEL_ACK (0x53) /* ISurf USB + 3070 */ |
149 | #define HD_CLOSE_B1CHANNEL_ACK (0x53) // ISurf USB + 3070 | 147 | #define HD_CLOSE_B2CHANNEL_ACK (0x54) /* ISurf USB + 3070 */ |
150 | #define HD_CLOSE_B2CHANNEL_ACK (0x54) // ISurf USB + 3070 | 148 | #define HD_SUSPEND_END (0x61) /* ISurf USB */ |
151 | // Powermangment | 149 | #define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) /* ISurf USB + 3070 */ |
152 | #define HD_SUSPEND_END (0x61) // ISurf USB | 150 | |
153 | // Configuration | 151 | /* control requests */ |
154 | #define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) // ISurf USB + 3070 | 152 | #define HD_OPEN_B1CHANNEL (0x23) /* ISurf USB + 3070 */ |
155 | 153 | #define HD_CLOSE_B1CHANNEL (0x24) /* ISurf USB + 3070 */ | |
156 | /* control requests 3070 */ | 154 | #define HD_OPEN_B2CHANNEL (0x25) /* ISurf USB + 3070 */ |
157 | #define HD_OPEN_B1CHANNEL (0x23) // ISurf USB + 3070 | 155 | #define HD_CLOSE_B2CHANNEL (0x26) /* ISurf USB + 3070 */ |
158 | #define HD_CLOSE_B1CHANNEL (0x24) // ISurf USB + 3070 | 156 | #define HD_RESET_INTERRUPT_PIPE (0x27) /* ISurf USB + 3070 */ |
159 | #define HD_OPEN_B2CHANNEL (0x25) // ISurf USB + 3070 | 157 | #define HD_DEVICE_INIT_ACK (0x34) /* ISurf USB + 3070 */ |
160 | #define HD_CLOSE_B2CHANNEL (0x26) // ISurf USB + 3070 | 158 | #define HD_WRITE_ATMESSAGE (0x12) /* 3070 */ |
161 | #define HD_RESET_INTERRUPT_PIPE (0x27) // ISurf USB + 3070 | 159 | #define HD_READ_ATMESSAGE (0x13) /* 3070 */ |
162 | #define HD_DEVICE_INIT_ACK (0x34) // ISurf USB + 3070 | 160 | #define HD_OPEN_ATCHANNEL (0x28) /* 3070 */ |
163 | #define HD_WRITE_ATMESSAGE (0x12) // 3070 | 161 | #define HD_CLOSE_ATCHANNEL (0x29) /* 3070 */ |
164 | #define HD_READ_ATMESSAGE (0x13) // 3070 | ||
165 | #define HD_OPEN_ATCHANNEL (0x28) // 3070 | ||
166 | #define HD_CLOSE_ATCHANNEL (0x29) // 3070 | ||
167 | 162 | ||
168 | /* number of B channels supported by base driver */ | 163 | /* number of B channels supported by base driver */ |
169 | #define BAS_CHANNELS 2 | 164 | #define BAS_CHANNELS 2 |
@@ -193,7 +188,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
193 | #define AT_PROTO 4 | 188 | #define AT_PROTO 4 |
194 | #define AT_TYPE 5 | 189 | #define AT_TYPE 5 |
195 | #define AT_HLC 6 | 190 | #define AT_HLC 6 |
196 | #define AT_NUM 7 | 191 | #define AT_CLIP 7 |
192 | /* total number */ | ||
193 | #define AT_NUM 8 | ||
197 | 194 | ||
198 | /* variables in struct at_state_t */ | 195 | /* variables in struct at_state_t */ |
199 | #define VAR_ZSAU 0 | 196 | #define VAR_ZSAU 0 |
@@ -216,7 +213,6 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
216 | #define EV_START -110 | 213 | #define EV_START -110 |
217 | #define EV_STOP -111 | 214 | #define EV_STOP -111 |
218 | #define EV_IF_LOCK -112 | 215 | #define EV_IF_LOCK -112 |
219 | #define EV_PROTO_L2 -113 | ||
220 | #define EV_ACCEPT -114 | 216 | #define EV_ACCEPT -114 |
221 | #define EV_DIAL -115 | 217 | #define EV_DIAL -115 |
222 | #define EV_HUP -116 | 218 | #define EV_HUP -116 |
@@ -224,12 +220,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
224 | #define EV_BC_CLOSED -118 | 220 | #define EV_BC_CLOSED -118 |
225 | 221 | ||
226 | /* input state */ | 222 | /* input state */ |
227 | #define INS_command 0x0001 | 223 | #define INS_command 0x0001 /* receiving messages (not payload data) */ |
228 | #define INS_DLE_char 0x0002 | 224 | #define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */ |
229 | #define INS_byte_stuff 0x0004 | 225 | #define INS_byte_stuff 0x0004 |
230 | #define INS_have_data 0x0008 | 226 | #define INS_have_data 0x0008 |
231 | #define INS_skip_frame 0x0010 | 227 | #define INS_DLE_command 0x0020 /* DLE message start (<DLE> X) received */ |
232 | #define INS_DLE_command 0x0020 | ||
233 | #define INS_flag_hunt 0x0040 | 228 | #define INS_flag_hunt 0x0040 |
234 | 229 | ||
235 | /* channel state */ | 230 | /* channel state */ |
@@ -259,6 +254,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
259 | #define SM_LOCKED 0 | 254 | #define SM_LOCKED 0 |
260 | #define SM_ISDN 1 /* default */ | 255 | #define SM_ISDN 1 /* default */ |
261 | 256 | ||
257 | /* layer 2 protocols (AT^SBPR=...) */ | ||
258 | #define L2_BITSYNC 0 | ||
259 | #define L2_HDLC 1 | ||
260 | #define L2_VOICE 2 | ||
261 | |||
262 | struct gigaset_ops; | 262 | struct gigaset_ops; |
263 | struct gigaset_driver; | 263 | struct gigaset_driver; |
264 | 264 | ||
@@ -286,8 +286,6 @@ extern struct reply_t gigaset_tab_cid[]; | |||
286 | extern struct reply_t gigaset_tab_nocid[]; | 286 | extern struct reply_t gigaset_tab_nocid[]; |
287 | 287 | ||
288 | struct inbuf_t { | 288 | struct inbuf_t { |
289 | unsigned char *rcvbuf; /* usb-gigaset receive buffer */ | ||
290 | struct bc_state *bcs; | ||
291 | struct cardstate *cs; | 289 | struct cardstate *cs; |
292 | int inputstate; | 290 | int inputstate; |
293 | int head, tail; | 291 | int head, tail; |
@@ -359,12 +357,6 @@ struct at_state_t { | |||
359 | struct bc_state *bcs; | 357 | struct bc_state *bcs; |
360 | }; | 358 | }; |
361 | 359 | ||
362 | struct resp_type_t { | ||
363 | unsigned char *response; | ||
364 | int resp_code; /* RSP_XXXX */ | ||
365 | int type; /* RT_XXXX */ | ||
366 | }; | ||
367 | |||
368 | struct event_t { | 360 | struct event_t { |
369 | int type; | 361 | int type; |
370 | void *ptr, *arg; | 362 | void *ptr, *arg; |
@@ -395,7 +387,7 @@ struct bc_state { | |||
395 | 387 | ||
396 | unsigned chstate; /* bitmap (CHS_*) */ | 388 | unsigned chstate; /* bitmap (CHS_*) */ |
397 | int ignore; | 389 | int ignore; |
398 | unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */ | 390 | unsigned proto2; /* layer 2 protocol (L2_*) */ |
399 | char *commands[AT_NUM]; /* see AT_XXXX */ | 391 | char *commands[AT_NUM]; /* see AT_XXXX */ |
400 | 392 | ||
401 | #ifdef CONFIG_GIGASET_DEBUG | 393 | #ifdef CONFIG_GIGASET_DEBUG |
@@ -410,6 +402,8 @@ struct bc_state { | |||
410 | struct usb_bc_state *usb; /* usb hardware driver (m105) */ | 402 | struct usb_bc_state *usb; /* usb hardware driver (m105) */ |
411 | struct bas_bc_state *bas; /* usb hardware driver (base) */ | 403 | struct bas_bc_state *bas; /* usb hardware driver (base) */ |
412 | } hw; | 404 | } hw; |
405 | |||
406 | void *ap; /* LL application structure */ | ||
413 | }; | 407 | }; |
414 | 408 | ||
415 | struct cardstate { | 409 | struct cardstate { |
@@ -456,12 +450,13 @@ struct cardstate { | |||
456 | 450 | ||
457 | unsigned running; /* !=0 if events are handled */ | 451 | unsigned running; /* !=0 if events are handled */ |
458 | unsigned connected; /* !=0 if hardware is connected */ | 452 | unsigned connected; /* !=0 if hardware is connected */ |
459 | unsigned isdn_up; /* !=0 after ISDN_STAT_RUN */ | 453 | unsigned isdn_up; /* !=0 after gigaset_isdn_start() */ |
460 | 454 | ||
461 | unsigned cidmode; | 455 | unsigned cidmode; |
462 | 456 | ||
463 | int myid; /* id for communication with LL */ | 457 | int myid; /* id for communication with LL */ |
464 | isdn_if iif; | 458 | void *iif; /* LL interface structure */ |
459 | unsigned short hw_hdr_len; /* headroom needed in data skbs */ | ||
465 | 460 | ||
466 | struct reply_t *tabnocid; | 461 | struct reply_t *tabnocid; |
467 | struct reply_t *tabcid; | 462 | struct reply_t *tabcid; |
@@ -476,8 +471,8 @@ struct cardstate { | |||
476 | 471 | ||
477 | struct timer_list timer; | 472 | struct timer_list timer; |
478 | int retry_count; | 473 | int retry_count; |
479 | int dle; /* !=0 if modem commands/responses are | 474 | int dle; /* !=0 if DLE mode is active |
480 | dle encoded */ | 475 | (ZDLE=1 received -- M10x only) */ |
481 | int cur_at_seq; /* sequence of AT commands being | 476 | int cur_at_seq; /* sequence of AT commands being |
482 | processed */ | 477 | processed */ |
483 | int curchannel; /* channel those commands are meant | 478 | int curchannel; /* channel those commands are meant |
@@ -616,7 +611,9 @@ struct gigaset_ops { | |||
616 | int (*baud_rate)(struct cardstate *cs, unsigned cflag); | 611 | int (*baud_rate)(struct cardstate *cs, unsigned cflag); |
617 | int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); | 612 | int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); |
618 | 613 | ||
619 | /* Called from i4l.c to put an skb into the send-queue. */ | 614 | /* Called from LL interface to put an skb into the send-queue. |
615 | * After sending is completed, gigaset_skb_sent() must be called | ||
616 | * with the skb's link layer header preserved. */ | ||
620 | int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); | 617 | int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); |
621 | 618 | ||
622 | /* Called from ev-layer.c to process a block of data | 619 | /* Called from ev-layer.c to process a block of data |
@@ -625,7 +622,8 @@ struct gigaset_ops { | |||
625 | 622 | ||
626 | }; | 623 | }; |
627 | 624 | ||
628 | /* = Common structures and definitions ======================================= */ | 625 | /* = Common structures and definitions ======================================= |
626 | */ | ||
629 | 627 | ||
630 | /* Parser states for DLE-Event: | 628 | /* Parser states for DLE-Event: |
631 | * <DLE-EVENT>: <DLE_FLAG> "X" <EVENT> <DLE_FLAG> "." | 629 | * <DLE-EVENT>: <DLE_FLAG> "X" <EVENT> <DLE_FLAG> "." |
@@ -638,8 +636,7 @@ struct gigaset_ops { | |||
638 | * Functions implemented in asyncdata.c | 636 | * Functions implemented in asyncdata.c |
639 | */ | 637 | */ |
640 | 638 | ||
641 | /* Called from i4l.c to put an skb into the send-queue. | 639 | /* Called from LL interface to put an skb into the send queue. */ |
642 | * After sending gigaset_skb_sent() should be called. */ | ||
643 | int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb); | 640 | int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb); |
644 | 641 | ||
645 | /* Called from ev-layer.c to process a block of data | 642 | /* Called from ev-layer.c to process a block of data |
@@ -650,8 +647,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf); | |||
650 | * Functions implemented in isocdata.c | 647 | * Functions implemented in isocdata.c |
651 | */ | 648 | */ |
652 | 649 | ||
653 | /* Called from i4l.c to put an skb into the send-queue. | 650 | /* Called from LL interface to put an skb into the send queue. */ |
654 | * After sending gigaset_skb_sent() should be called. */ | ||
655 | int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb); | 651 | int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb); |
656 | 652 | ||
657 | /* Called from ev-layer.c to process a block of data | 653 | /* Called from ev-layer.c to process a block of data |
@@ -674,36 +670,26 @@ void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle); | |||
674 | int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); | 670 | int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); |
675 | 671 | ||
676 | /* =========================================================================== | 672 | /* =========================================================================== |
677 | * Functions implemented in i4l.c/gigaset.h | 673 | * Functions implemented in LL interface |
678 | */ | 674 | */ |
679 | 675 | ||
680 | /* Called by gigaset_initcs() for setting up with the isdn4linux subsystem */ | 676 | /* Called from common.c for setting up/shutting down with the ISDN subsystem */ |
681 | int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid); | 677 | int gigaset_isdn_register(struct cardstate *cs, const char *isdnid); |
678 | void gigaset_isdn_unregister(struct cardstate *cs); | ||
682 | 679 | ||
683 | /* Called from xxx-gigaset.c to indicate completion of sending an skb */ | 680 | /* Called from hardware module to indicate completion of an skb */ |
684 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); | 681 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); |
682 | void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb); | ||
683 | void gigaset_isdn_rcv_err(struct bc_state *bcs); | ||
685 | 684 | ||
686 | /* Called from common.c/ev-layer.c to indicate events relevant to the LL */ | 685 | /* Called from common.c/ev-layer.c to indicate events relevant to the LL */ |
686 | void gigaset_isdn_start(struct cardstate *cs); | ||
687 | void gigaset_isdn_stop(struct cardstate *cs); | ||
687 | int gigaset_isdn_icall(struct at_state_t *at_state); | 688 | int gigaset_isdn_icall(struct at_state_t *at_state); |
688 | int gigaset_isdn_setup_accept(struct at_state_t *at_state); | 689 | void gigaset_isdn_connD(struct bc_state *bcs); |
689 | int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data); | 690 | void gigaset_isdn_hupD(struct bc_state *bcs); |
690 | 691 | void gigaset_isdn_connB(struct bc_state *bcs); | |
691 | void gigaset_i4l_cmd(struct cardstate *cs, int cmd); | 692 | void gigaset_isdn_hupB(struct bc_state *bcs); |
692 | void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd); | ||
693 | |||
694 | |||
695 | static inline void gigaset_isdn_rcv_err(struct bc_state *bcs) | ||
696 | { | ||
697 | isdn_ctrl response; | ||
698 | |||
699 | /* error -> LL */ | ||
700 | gig_dbg(DEBUG_CMD, "sending L1ERR"); | ||
701 | response.driver = bcs->cs->myid; | ||
702 | response.command = ISDN_STAT_L1ERR; | ||
703 | response.arg = bcs->channel; | ||
704 | response.parm.errcode = ISDN_STAT_L1ERR_RECV; | ||
705 | bcs->cs->iif.statcallb(&response); | ||
706 | } | ||
707 | 693 | ||
708 | /* =========================================================================== | 694 | /* =========================================================================== |
709 | * Functions implemented in ev-layer.c | 695 | * Functions implemented in ev-layer.c |
@@ -732,6 +718,7 @@ void gigaset_bcs_reinit(struct bc_state *bcs); | |||
732 | void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, | 718 | void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, |
733 | struct cardstate *cs, int cid); | 719 | struct cardstate *cs, int cid); |
734 | int gigaset_get_channel(struct bc_state *bcs); | 720 | int gigaset_get_channel(struct bc_state *bcs); |
721 | struct bc_state *gigaset_get_free_channel(struct cardstate *cs); | ||
735 | void gigaset_free_channel(struct bc_state *bcs); | 722 | void gigaset_free_channel(struct bc_state *bcs); |
736 | int gigaset_get_channels(struct cardstate *cs); | 723 | int gigaset_get_channels(struct cardstate *cs); |
737 | void gigaset_free_channels(struct cardstate *cs); | 724 | void gigaset_free_channels(struct cardstate *cs); |
@@ -781,7 +768,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs, | |||
781 | void *ptr, int parameter, void *arg); | 768 | void *ptr, int parameter, void *arg); |
782 | 769 | ||
783 | /* Called on CONFIG1 command from frontend. */ | 770 | /* Called on CONFIG1 command from frontend. */ |
784 | int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode | 771 | int gigaset_enterconfigmode(struct cardstate *cs); |
785 | 772 | ||
786 | /* cs->lock must not be locked */ | 773 | /* cs->lock must not be locked */ |
787 | static inline void gigaset_schedule_event(struct cardstate *cs) | 774 | static inline void gigaset_schedule_event(struct cardstate *cs) |
@@ -816,35 +803,6 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs) | |||
816 | /* handling routines for sk_buff */ | 803 | /* handling routines for sk_buff */ |
817 | /* ============================= */ | 804 | /* ============================= */ |
818 | 805 | ||
819 | /* pass received skb to LL | ||
820 | * Warning: skb must not be accessed anymore! | ||
821 | */ | ||
822 | static inline void gigaset_rcv_skb(struct sk_buff *skb, | ||
823 | struct cardstate *cs, | ||
824 | struct bc_state *bcs) | ||
825 | { | ||
826 | cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb); | ||
827 | bcs->trans_down++; | ||
828 | } | ||
829 | |||
830 | /* handle reception of corrupted skb | ||
831 | * Warning: skb must not be accessed anymore! | ||
832 | */ | ||
833 | static inline void gigaset_rcv_error(struct sk_buff *procskb, | ||
834 | struct cardstate *cs, | ||
835 | struct bc_state *bcs) | ||
836 | { | ||
837 | if (procskb) | ||
838 | dev_kfree_skb(procskb); | ||
839 | |||
840 | if (bcs->ignore) | ||
841 | --bcs->ignore; | ||
842 | else { | ||
843 | ++bcs->corrupted; | ||
844 | gigaset_isdn_rcv_err(bcs); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | /* append received bytes to inbuf */ | 806 | /* append received bytes to inbuf */ |
849 | int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, | 807 | int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, |
850 | unsigned numbytes); | 808 | unsigned numbytes); |
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 654489d836cd..c129ee47a8fb 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c | |||
@@ -14,6 +14,9 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "gigaset.h" | 16 | #include "gigaset.h" |
17 | #include <linux/isdnif.h> | ||
18 | |||
19 | #define HW_HDR_LEN 2 /* Header size used to store ack info */ | ||
17 | 20 | ||
18 | /* == Handling of I4L IO =====================================================*/ | 21 | /* == Handling of I4L IO =====================================================*/ |
19 | 22 | ||
@@ -36,12 +39,12 @@ | |||
36 | static int writebuf_from_LL(int driverID, int channel, int ack, | 39 | static int writebuf_from_LL(int driverID, int channel, int ack, |
37 | struct sk_buff *skb) | 40 | struct sk_buff *skb) |
38 | { | 41 | { |
39 | struct cardstate *cs; | 42 | struct cardstate *cs = gigaset_get_cs_by_id(driverID); |
40 | struct bc_state *bcs; | 43 | struct bc_state *bcs; |
44 | unsigned char *ack_header; | ||
41 | unsigned len; | 45 | unsigned len; |
42 | unsigned skblen; | ||
43 | 46 | ||
44 | if (!(cs = gigaset_get_cs_by_id(driverID))) { | 47 | if (!cs) { |
45 | pr_err("%s: invalid driver ID (%d)\n", __func__, driverID); | 48 | pr_err("%s: invalid driver ID (%d)\n", __func__, driverID); |
46 | return -ENODEV; | 49 | return -ENODEV; |
47 | } | 50 | } |
@@ -75,11 +78,23 @@ static int writebuf_from_LL(int driverID, int channel, int ack, | |||
75 | return -EINVAL; | 78 | return -EINVAL; |
76 | } | 79 | } |
77 | 80 | ||
78 | skblen = ack ? len : 0; | 81 | /* set up acknowledgement header */ |
79 | skb->head[0] = skblen & 0xff; | 82 | if (skb_headroom(skb) < HW_HDR_LEN) { |
80 | skb->head[1] = skblen >> 8; | 83 | /* should never happen */ |
81 | gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", | 84 | dev_err(cs->dev, "%s: insufficient skb headroom\n", __func__); |
82 | len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); | 85 | return -ENOMEM; |
86 | } | ||
87 | skb_set_mac_header(skb, -HW_HDR_LEN); | ||
88 | skb->mac_len = HW_HDR_LEN; | ||
89 | ack_header = skb_mac_header(skb); | ||
90 | if (ack) { | ||
91 | ack_header[0] = len & 0xff; | ||
92 | ack_header[1] = len >> 8; | ||
93 | } else { | ||
94 | ack_header[0] = ack_header[1] = 0; | ||
95 | } | ||
96 | gig_dbg(DEBUG_MCMD, "skb: len=%u, ack=%d: %02x %02x", | ||
97 | len, ack, ack_header[0], ack_header[1]); | ||
83 | 98 | ||
84 | /* pass to device-specific module */ | 99 | /* pass to device-specific module */ |
85 | return cs->ops->send_skb(bcs, skb); | 100 | return cs->ops->send_skb(bcs, skb); |
@@ -95,6 +110,8 @@ static int writebuf_from_LL(int driverID, int channel, int ack, | |||
95 | */ | 110 | */ |
96 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | 111 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) |
97 | { | 112 | { |
113 | isdn_if *iif = bcs->cs->iif; | ||
114 | unsigned char *ack_header = skb_mac_header(skb); | ||
98 | unsigned len; | 115 | unsigned len; |
99 | isdn_ctrl response; | 116 | isdn_ctrl response; |
100 | 117 | ||
@@ -104,8 +121,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | |||
104 | dev_warn(bcs->cs->dev, "%s: skb->len==%d\n", | 121 | dev_warn(bcs->cs->dev, "%s: skb->len==%d\n", |
105 | __func__, skb->len); | 122 | __func__, skb->len); |
106 | 123 | ||
107 | len = (unsigned char) skb->head[0] | | 124 | len = ack_header[0] + ((unsigned) ack_header[1] << 8); |
108 | (unsigned) (unsigned char) skb->head[1] << 8; | ||
109 | if (len) { | 125 | if (len) { |
110 | gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)", | 126 | gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)", |
111 | bcs->cs->myid, bcs->channel, len); | 127 | bcs->cs->myid, bcs->channel, len); |
@@ -114,71 +130,177 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | |||
114 | response.command = ISDN_STAT_BSENT; | 130 | response.command = ISDN_STAT_BSENT; |
115 | response.arg = bcs->channel; | 131 | response.arg = bcs->channel; |
116 | response.parm.length = len; | 132 | response.parm.length = len; |
117 | bcs->cs->iif.statcallb(&response); | 133 | iif->statcallb(&response); |
118 | } | 134 | } |
119 | } | 135 | } |
120 | EXPORT_SYMBOL_GPL(gigaset_skb_sent); | 136 | EXPORT_SYMBOL_GPL(gigaset_skb_sent); |
121 | 137 | ||
138 | /** | ||
139 | * gigaset_skb_rcvd() - pass received skb to LL | ||
140 | * @bcs: B channel descriptor structure. | ||
141 | * @skb: received data. | ||
142 | * | ||
143 | * Called by hardware module {bas,ser,usb}_gigaset when user data has | ||
144 | * been successfully received, for passing to the LL. | ||
145 | * Warning: skb must not be accessed anymore! | ||
146 | */ | ||
147 | void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) | ||
148 | { | ||
149 | isdn_if *iif = bcs->cs->iif; | ||
150 | |||
151 | iif->rcvcallb_skb(bcs->cs->myid, bcs->channel, skb); | ||
152 | bcs->trans_down++; | ||
153 | } | ||
154 | EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); | ||
155 | |||
156 | /** | ||
157 | * gigaset_isdn_rcv_err() - signal receive error | ||
158 | * @bcs: B channel descriptor structure. | ||
159 | * | ||
160 | * Called by hardware module {bas,ser,usb}_gigaset when a receive error | ||
161 | * has occurred, for signalling to the LL. | ||
162 | */ | ||
163 | void gigaset_isdn_rcv_err(struct bc_state *bcs) | ||
164 | { | ||
165 | isdn_if *iif = bcs->cs->iif; | ||
166 | isdn_ctrl response; | ||
167 | |||
168 | /* if currently ignoring packets, just count down */ | ||
169 | if (bcs->ignore) { | ||
170 | bcs->ignore--; | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | /* update statistics */ | ||
175 | bcs->corrupted++; | ||
176 | |||
177 | /* error -> LL */ | ||
178 | gig_dbg(DEBUG_CMD, "sending L1ERR"); | ||
179 | response.driver = bcs->cs->myid; | ||
180 | response.command = ISDN_STAT_L1ERR; | ||
181 | response.arg = bcs->channel; | ||
182 | response.parm.errcode = ISDN_STAT_L1ERR_RECV; | ||
183 | iif->statcallb(&response); | ||
184 | } | ||
185 | EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); | ||
186 | |||
122 | /* This function will be called by LL to send commands | 187 | /* This function will be called by LL to send commands |
123 | * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL, | 188 | * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL, |
124 | * so don't put too much effort into it. | 189 | * so don't put too much effort into it. |
125 | */ | 190 | */ |
126 | static int command_from_LL(isdn_ctrl *cntrl) | 191 | static int command_from_LL(isdn_ctrl *cntrl) |
127 | { | 192 | { |
128 | struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver); | 193 | struct cardstate *cs; |
129 | struct bc_state *bcs; | 194 | struct bc_state *bcs; |
130 | int retval = 0; | 195 | int retval = 0; |
131 | struct setup_parm *sp; | 196 | char **commands; |
197 | int ch; | ||
198 | int i; | ||
199 | size_t l; | ||
132 | 200 | ||
133 | gigaset_debugdrivers(); | 201 | gigaset_debugdrivers(); |
134 | 202 | ||
135 | if (!cs) { | 203 | gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx", |
204 | cntrl->driver, cntrl->command, cntrl->arg); | ||
205 | |||
206 | cs = gigaset_get_cs_by_id(cntrl->driver); | ||
207 | if (cs == NULL) { | ||
136 | pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver); | 208 | pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver); |
137 | return -ENODEV; | 209 | return -ENODEV; |
138 | } | 210 | } |
211 | ch = cntrl->arg & 0xff; | ||
139 | 212 | ||
140 | switch (cntrl->command) { | 213 | switch (cntrl->command) { |
141 | case ISDN_CMD_IOCTL: | 214 | case ISDN_CMD_IOCTL: |
142 | gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)", | ||
143 | cntrl->driver, cntrl->arg); | ||
144 | |||
145 | dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n"); | 215 | dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n"); |
146 | return -EINVAL; | 216 | return -EINVAL; |
147 | 217 | ||
148 | case ISDN_CMD_DIAL: | 218 | case ISDN_CMD_DIAL: |
149 | gig_dbg(DEBUG_ANY, | 219 | gig_dbg(DEBUG_ANY, |
150 | "ISDN_CMD_DIAL (driver: %d, ch: %ld, " | 220 | "ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)", |
151 | "phone: %s, ownmsn: %s, si1: %d, si2: %d)", | ||
152 | cntrl->driver, cntrl->arg, | ||
153 | cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, | 221 | cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, |
154 | cntrl->parm.setup.si1, cntrl->parm.setup.si2); | 222 | cntrl->parm.setup.si1, cntrl->parm.setup.si2); |
155 | 223 | ||
156 | if (cntrl->arg >= cs->channels) { | 224 | if (ch >= cs->channels) { |
157 | dev_err(cs->dev, | 225 | dev_err(cs->dev, |
158 | "ISDN_CMD_DIAL: invalid channel (%d)\n", | 226 | "ISDN_CMD_DIAL: invalid channel (%d)\n", ch); |
159 | (int) cntrl->arg); | ||
160 | return -EINVAL; | 227 | return -EINVAL; |
161 | } | 228 | } |
162 | 229 | bcs = cs->bcs + ch; | |
163 | bcs = cs->bcs + cntrl->arg; | ||
164 | |||
165 | if (!gigaset_get_channel(bcs)) { | 230 | if (!gigaset_get_channel(bcs)) { |
166 | dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); | 231 | dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); |
167 | return -EBUSY; | 232 | return -EBUSY; |
168 | } | 233 | } |
169 | 234 | ||
170 | sp = kmalloc(sizeof *sp, GFP_ATOMIC); | 235 | commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC); |
171 | if (!sp) { | 236 | if (!commands) { |
172 | gigaset_free_channel(bcs); | 237 | gigaset_free_channel(bcs); |
173 | dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n"); | 238 | dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n"); |
174 | return -ENOMEM; | 239 | return -ENOMEM; |
175 | } | 240 | } |
176 | *sp = cntrl->parm.setup; | ||
177 | 241 | ||
178 | if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, | 242 | l = 3 + strlen(cntrl->parm.setup.phone); |
243 | commands[AT_DIAL] = kmalloc(l, GFP_ATOMIC); | ||
244 | if (!commands[AT_DIAL]) | ||
245 | goto oom; | ||
246 | if (cntrl->parm.setup.phone[0] == '*' && | ||
247 | cntrl->parm.setup.phone[1] == '*') { | ||
248 | /* internal call: translate ** prefix to CTP value */ | ||
249 | commands[AT_TYPE] = kstrdup("^SCTP=0\r", GFP_ATOMIC); | ||
250 | if (!commands[AT_TYPE]) | ||
251 | goto oom; | ||
252 | snprintf(commands[AT_DIAL], l, | ||
253 | "D%s\r", cntrl->parm.setup.phone+2); | ||
254 | } else { | ||
255 | commands[AT_TYPE] = kstrdup("^SCTP=1\r", GFP_ATOMIC); | ||
256 | if (!commands[AT_TYPE]) | ||
257 | goto oom; | ||
258 | snprintf(commands[AT_DIAL], l, | ||
259 | "D%s\r", cntrl->parm.setup.phone); | ||
260 | } | ||
261 | |||
262 | l = strlen(cntrl->parm.setup.eazmsn); | ||
263 | if (l) { | ||
264 | l += 8; | ||
265 | commands[AT_MSN] = kmalloc(l, GFP_ATOMIC); | ||
266 | if (!commands[AT_MSN]) | ||
267 | goto oom; | ||
268 | snprintf(commands[AT_MSN], l, "^SMSN=%s\r", | ||
269 | cntrl->parm.setup.eazmsn); | ||
270 | } | ||
271 | |||
272 | switch (cntrl->parm.setup.si1) { | ||
273 | case 1: /* audio */ | ||
274 | /* BC = 9090A3: 3.1 kHz audio, A-law */ | ||
275 | commands[AT_BC] = kstrdup("^SBC=9090A3\r", GFP_ATOMIC); | ||
276 | if (!commands[AT_BC]) | ||
277 | goto oom; | ||
278 | break; | ||
279 | case 7: /* data */ | ||
280 | default: /* hope the app knows what it is doing */ | ||
281 | /* BC = 8890: unrestricted digital information */ | ||
282 | commands[AT_BC] = kstrdup("^SBC=8890\r", GFP_ATOMIC); | ||
283 | if (!commands[AT_BC]) | ||
284 | goto oom; | ||
285 | } | ||
286 | /* ToDo: other si1 values, inspect si2, set HLC/LLC */ | ||
287 | |||
288 | commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); | ||
289 | if (!commands[AT_PROTO]) | ||
290 | goto oom; | ||
291 | snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); | ||
292 | |||
293 | commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); | ||
294 | if (!commands[AT_ISO]) | ||
295 | goto oom; | ||
296 | snprintf(commands[AT_ISO], 9, "^SISO=%u\r", | ||
297 | (unsigned) bcs->channel + 1); | ||
298 | |||
299 | if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, | ||
179 | bcs->at_state.seq_index, NULL)) { | 300 | bcs->at_state.seq_index, NULL)) { |
180 | //FIXME what should we do? | 301 | for (i = 0; i < AT_NUM; ++i) |
181 | kfree(sp); | 302 | kfree(commands[i]); |
303 | kfree(commands); | ||
182 | gigaset_free_channel(bcs); | 304 | gigaset_free_channel(bcs); |
183 | return -ENOMEM; | 305 | return -ENOMEM; |
184 | } | 306 | } |
@@ -186,115 +308,102 @@ static int command_from_LL(isdn_ctrl *cntrl) | |||
186 | gig_dbg(DEBUG_CMD, "scheduling DIAL"); | 308 | gig_dbg(DEBUG_CMD, "scheduling DIAL"); |
187 | gigaset_schedule_event(cs); | 309 | gigaset_schedule_event(cs); |
188 | break; | 310 | break; |
189 | case ISDN_CMD_ACCEPTD: //FIXME | 311 | case ISDN_CMD_ACCEPTD: |
190 | gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); | 312 | if (ch >= cs->channels) { |
191 | |||
192 | if (cntrl->arg >= cs->channels) { | ||
193 | dev_err(cs->dev, | 313 | dev_err(cs->dev, |
194 | "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", | 314 | "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch); |
195 | (int) cntrl->arg); | ||
196 | return -EINVAL; | 315 | return -EINVAL; |
197 | } | 316 | } |
198 | 317 | bcs = cs->bcs + ch; | |
199 | if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, | 318 | if (!gigaset_add_event(cs, &bcs->at_state, |
200 | EV_ACCEPT, NULL, 0, NULL)) { | 319 | EV_ACCEPT, NULL, 0, NULL)) |
201 | //FIXME what should we do? | ||
202 | return -ENOMEM; | 320 | return -ENOMEM; |
203 | } | ||
204 | 321 | ||
205 | gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); | 322 | gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); |
206 | gigaset_schedule_event(cs); | 323 | gigaset_schedule_event(cs); |
207 | 324 | ||
208 | break; | 325 | break; |
209 | case ISDN_CMD_ACCEPTB: | 326 | case ISDN_CMD_ACCEPTB: |
210 | gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB"); | ||
211 | break; | 327 | break; |
212 | case ISDN_CMD_HANGUP: | 328 | case ISDN_CMD_HANGUP: |
213 | gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)", | 329 | if (ch >= cs->channels) { |
214 | (int) cntrl->arg); | ||
215 | |||
216 | if (cntrl->arg >= cs->channels) { | ||
217 | dev_err(cs->dev, | 330 | dev_err(cs->dev, |
218 | "ISDN_CMD_HANGUP: invalid channel (%d)\n", | 331 | "ISDN_CMD_HANGUP: invalid channel (%d)\n", ch); |
219 | (int) cntrl->arg); | ||
220 | return -EINVAL; | 332 | return -EINVAL; |
221 | } | 333 | } |
222 | 334 | bcs = cs->bcs + ch; | |
223 | if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, | 335 | if (!gigaset_add_event(cs, &bcs->at_state, |
224 | EV_HUP, NULL, 0, NULL)) { | 336 | EV_HUP, NULL, 0, NULL)) |
225 | //FIXME what should we do? | ||
226 | return -ENOMEM; | 337 | return -ENOMEM; |
227 | } | ||
228 | 338 | ||
229 | gig_dbg(DEBUG_CMD, "scheduling HUP"); | 339 | gig_dbg(DEBUG_CMD, "scheduling HUP"); |
230 | gigaset_schedule_event(cs); | 340 | gigaset_schedule_event(cs); |
231 | 341 | ||
232 | break; | 342 | break; |
233 | case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME | 343 | case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ |
234 | gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); | 344 | dev_info(cs->dev, "ignoring ISDN_CMD_CLREAZ\n"); |
235 | break; | 345 | break; |
236 | case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME | 346 | case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ |
237 | gig_dbg(DEBUG_ANY, | 347 | dev_info(cs->dev, "ignoring ISDN_CMD_SETEAZ (%s)\n", |
238 | "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)", | 348 | cntrl->parm.num); |
239 | cntrl->driver, cntrl->arg, cntrl->parm.num); | ||
240 | break; | 349 | break; |
241 | case ISDN_CMD_SETL2: /* Set L2 to given protocol */ | 350 | case ISDN_CMD_SETL2: /* Set L2 to given protocol */ |
242 | gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)", | 351 | if (ch >= cs->channels) { |
243 | cntrl->arg & 0xff, (cntrl->arg >> 8)); | ||
244 | |||
245 | if ((cntrl->arg & 0xff) >= cs->channels) { | ||
246 | dev_err(cs->dev, | 352 | dev_err(cs->dev, |
247 | "ISDN_CMD_SETL2: invalid channel (%d)\n", | 353 | "ISDN_CMD_SETL2: invalid channel (%d)\n", ch); |
248 | (int) cntrl->arg & 0xff); | ||
249 | return -EINVAL; | 354 | return -EINVAL; |
250 | } | 355 | } |
251 | 356 | bcs = cs->bcs + ch; | |
252 | if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state, | 357 | if (bcs->chstate & CHS_D_UP) { |
253 | EV_PROTO_L2, NULL, cntrl->arg >> 8, | 358 | dev_err(cs->dev, |
254 | NULL)) { | 359 | "ISDN_CMD_SETL2: channel active (%d)\n", ch); |
255 | //FIXME what should we do? | 360 | return -EINVAL; |
256 | return -ENOMEM; | 361 | } |
362 | switch (cntrl->arg >> 8) { | ||
363 | case ISDN_PROTO_L2_HDLC: | ||
364 | gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_HDLC"); | ||
365 | bcs->proto2 = L2_HDLC; | ||
366 | break; | ||
367 | case ISDN_PROTO_L2_TRANS: | ||
368 | gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_VOICE"); | ||
369 | bcs->proto2 = L2_VOICE; | ||
370 | break; | ||
371 | default: | ||
372 | dev_err(cs->dev, | ||
373 | "ISDN_CMD_SETL2: unsupported protocol (%lu)\n", | ||
374 | cntrl->arg >> 8); | ||
375 | return -EINVAL; | ||
257 | } | 376 | } |
258 | |||
259 | gig_dbg(DEBUG_CMD, "scheduling PROTO_L2"); | ||
260 | gigaset_schedule_event(cs); | ||
261 | break; | 377 | break; |
262 | case ISDN_CMD_SETL3: /* Set L3 to given protocol */ | 378 | case ISDN_CMD_SETL3: /* Set L3 to given protocol */ |
263 | gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)", | 379 | if (ch >= cs->channels) { |
264 | cntrl->arg & 0xff, (cntrl->arg >> 8)); | ||
265 | |||
266 | if ((cntrl->arg & 0xff) >= cs->channels) { | ||
267 | dev_err(cs->dev, | 380 | dev_err(cs->dev, |
268 | "ISDN_CMD_SETL3: invalid channel (%d)\n", | 381 | "ISDN_CMD_SETL3: invalid channel (%d)\n", ch); |
269 | (int) cntrl->arg & 0xff); | ||
270 | return -EINVAL; | 382 | return -EINVAL; |
271 | } | 383 | } |
272 | 384 | ||
273 | if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { | 385 | if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { |
274 | dev_err(cs->dev, | 386 | dev_err(cs->dev, |
275 | "ISDN_CMD_SETL3: invalid protocol %lu\n", | 387 | "ISDN_CMD_SETL3: unsupported protocol (%lu)\n", |
276 | cntrl->arg >> 8); | 388 | cntrl->arg >> 8); |
277 | return -EINVAL; | 389 | return -EINVAL; |
278 | } | 390 | } |
279 | 391 | ||
280 | break; | 392 | break; |
281 | case ISDN_CMD_PROCEED: | 393 | case ISDN_CMD_PROCEED: |
282 | gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME | 394 | gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); |
283 | break; | 395 | break; |
284 | case ISDN_CMD_ALERT: | 396 | case ISDN_CMD_ALERT: |
285 | gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME | 397 | gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); |
286 | if (cntrl->arg >= cs->channels) { | 398 | if (cntrl->arg >= cs->channels) { |
287 | dev_err(cs->dev, | 399 | dev_err(cs->dev, |
288 | "ISDN_CMD_ALERT: invalid channel (%d)\n", | 400 | "ISDN_CMD_ALERT: invalid channel (%d)\n", |
289 | (int) cntrl->arg); | 401 | (int) cntrl->arg); |
290 | return -EINVAL; | 402 | return -EINVAL; |
291 | } | 403 | } |
292 | //bcs = cs->bcs + cntrl->arg; | ||
293 | //bcs->proto2 = -1; | ||
294 | // FIXME | ||
295 | break; | 404 | break; |
296 | case ISDN_CMD_REDIR: | 405 | case ISDN_CMD_REDIR: |
297 | gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME | 406 | gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); |
298 | break; | 407 | break; |
299 | case ISDN_CMD_PROT_IO: | 408 | case ISDN_CMD_PROT_IO: |
300 | gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); | 409 | gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); |
@@ -324,149 +433,34 @@ static int command_from_LL(isdn_ctrl *cntrl) | |||
324 | } | 433 | } |
325 | 434 | ||
326 | return retval; | 435 | return retval; |
436 | |||
437 | oom: | ||
438 | dev_err(bcs->cs->dev, "out of memory\n"); | ||
439 | for (i = 0; i < AT_NUM; ++i) | ||
440 | kfree(commands[i]); | ||
441 | return -ENOMEM; | ||
327 | } | 442 | } |
328 | 443 | ||
329 | void gigaset_i4l_cmd(struct cardstate *cs, int cmd) | 444 | static void gigaset_i4l_cmd(struct cardstate *cs, int cmd) |
330 | { | 445 | { |
446 | isdn_if *iif = cs->iif; | ||
331 | isdn_ctrl command; | 447 | isdn_ctrl command; |
332 | 448 | ||
333 | command.driver = cs->myid; | 449 | command.driver = cs->myid; |
334 | command.command = cmd; | 450 | command.command = cmd; |
335 | command.arg = 0; | 451 | command.arg = 0; |
336 | cs->iif.statcallb(&command); | 452 | iif->statcallb(&command); |
337 | } | 453 | } |
338 | 454 | ||
339 | void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) | 455 | static void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) |
340 | { | 456 | { |
457 | isdn_if *iif = bcs->cs->iif; | ||
341 | isdn_ctrl command; | 458 | isdn_ctrl command; |
342 | 459 | ||
343 | command.driver = bcs->cs->myid; | 460 | command.driver = bcs->cs->myid; |
344 | command.command = cmd; | 461 | command.command = cmd; |
345 | command.arg = bcs->channel; | 462 | command.arg = bcs->channel; |
346 | bcs->cs->iif.statcallb(&command); | 463 | iif->statcallb(&command); |
347 | } | ||
348 | |||
349 | int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) | ||
350 | { | ||
351 | struct bc_state *bcs = at_state->bcs; | ||
352 | unsigned proto; | ||
353 | const char *bc; | ||
354 | size_t length[AT_NUM]; | ||
355 | size_t l; | ||
356 | int i; | ||
357 | struct setup_parm *sp = data; | ||
358 | |||
359 | switch (bcs->proto2) { | ||
360 | case ISDN_PROTO_L2_HDLC: | ||
361 | proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ | ||
362 | break; | ||
363 | case ISDN_PROTO_L2_TRANS: | ||
364 | proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ | ||
365 | break; | ||
366 | default: | ||
367 | dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n", | ||
368 | __func__, bcs->proto2); | ||
369 | return -EINVAL; | ||
370 | } | ||
371 | |||
372 | switch (sp->si1) { | ||
373 | case 1: /* audio */ | ||
374 | bc = "9090A3"; /* 3.1 kHz audio, A-law */ | ||
375 | break; | ||
376 | case 7: /* data */ | ||
377 | default: /* hope the app knows what it is doing */ | ||
378 | bc = "8890"; /* unrestricted digital information */ | ||
379 | } | ||
380 | //FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC | ||
381 | |||
382 | length[AT_DIAL ] = 1 + strlen(sp->phone) + 1 + 1; | ||
383 | l = strlen(sp->eazmsn); | ||
384 | length[AT_MSN ] = l ? 6 + l + 1 + 1 : 0; | ||
385 | length[AT_BC ] = 5 + strlen(bc) + 1 + 1; | ||
386 | length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ | ||
387 | length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ | ||
388 | length[AT_TYPE ] = 6 + 1 + 1 + 1; /* call type: 1 character */ | ||
389 | length[AT_HLC ] = 0; | ||
390 | |||
391 | for (i = 0; i < AT_NUM; ++i) { | ||
392 | kfree(bcs->commands[i]); | ||
393 | bcs->commands[i] = NULL; | ||
394 | if (length[i] && | ||
395 | !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { | ||
396 | dev_err(bcs->cs->dev, "out of memory\n"); | ||
397 | return -ENOMEM; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | /* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */ | ||
402 | if (sp->phone[0] == '*' && sp->phone[1] == '*') { | ||
403 | /* internal call: translate ** prefix to CTP value */ | ||
404 | snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], | ||
405 | "D%s\r", sp->phone+2); | ||
406 | strncpy(bcs->commands[AT_TYPE], "^SCTP=0\r", length[AT_TYPE]); | ||
407 | } else { | ||
408 | snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], | ||
409 | "D%s\r", sp->phone); | ||
410 | strncpy(bcs->commands[AT_TYPE], "^SCTP=1\r", length[AT_TYPE]); | ||
411 | } | ||
412 | |||
413 | if (bcs->commands[AT_MSN]) | ||
414 | snprintf(bcs->commands[AT_MSN], length[AT_MSN], | ||
415 | "^SMSN=%s\r", sp->eazmsn); | ||
416 | snprintf(bcs->commands[AT_BC ], length[AT_BC ], | ||
417 | "^SBC=%s\r", bc); | ||
418 | snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], | ||
419 | "^SBPR=%u\r", proto); | ||
420 | snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], | ||
421 | "^SISO=%u\r", (unsigned)bcs->channel + 1); | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | int gigaset_isdn_setup_accept(struct at_state_t *at_state) | ||
427 | { | ||
428 | unsigned proto; | ||
429 | size_t length[AT_NUM]; | ||
430 | int i; | ||
431 | struct bc_state *bcs = at_state->bcs; | ||
432 | |||
433 | switch (bcs->proto2) { | ||
434 | case ISDN_PROTO_L2_HDLC: | ||
435 | proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ | ||
436 | break; | ||
437 | case ISDN_PROTO_L2_TRANS: | ||
438 | proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ | ||
439 | break; | ||
440 | default: | ||
441 | dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n", | ||
442 | __func__, bcs->proto2); | ||
443 | return -EINVAL; | ||
444 | } | ||
445 | |||
446 | length[AT_DIAL ] = 0; | ||
447 | length[AT_MSN ] = 0; | ||
448 | length[AT_BC ] = 0; | ||
449 | length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ | ||
450 | length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ | ||
451 | length[AT_TYPE ] = 0; | ||
452 | length[AT_HLC ] = 0; | ||
453 | |||
454 | for (i = 0; i < AT_NUM; ++i) { | ||
455 | kfree(bcs->commands[i]); | ||
456 | bcs->commands[i] = NULL; | ||
457 | if (length[i] && | ||
458 | !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { | ||
459 | dev_err(at_state->cs->dev, "out of memory\n"); | ||
460 | return -ENOMEM; | ||
461 | } | ||
462 | } | ||
463 | |||
464 | snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], | ||
465 | "^SBPR=%u\r", proto); | ||
466 | snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], | ||
467 | "^SISO=%u\r", (unsigned) bcs->channel + 1); | ||
468 | |||
469 | return 0; | ||
470 | } | 464 | } |
471 | 465 | ||
472 | /** | 466 | /** |
@@ -482,13 +476,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state) | |||
482 | { | 476 | { |
483 | struct cardstate *cs = at_state->cs; | 477 | struct cardstate *cs = at_state->cs; |
484 | struct bc_state *bcs = at_state->bcs; | 478 | struct bc_state *bcs = at_state->bcs; |
479 | isdn_if *iif = cs->iif; | ||
485 | isdn_ctrl response; | 480 | isdn_ctrl response; |
486 | int retval; | 481 | int retval; |
487 | 482 | ||
488 | /* fill ICALL structure */ | 483 | /* fill ICALL structure */ |
489 | response.parm.setup.si1 = 0; /* default: unknown */ | 484 | response.parm.setup.si1 = 0; /* default: unknown */ |
490 | response.parm.setup.si2 = 0; | 485 | response.parm.setup.si2 = 0; |
491 | response.parm.setup.screen = 0; //FIXME how to set these? | 486 | response.parm.setup.screen = 0; |
492 | response.parm.setup.plan = 0; | 487 | response.parm.setup.plan = 0; |
493 | if (!at_state->str_var[STR_ZBC]) { | 488 | if (!at_state->str_var[STR_ZBC]) { |
494 | /* no BC (internal call): assume speech, A-law */ | 489 | /* no BC (internal call): assume speech, A-law */ |
@@ -509,29 +504,27 @@ int gigaset_isdn_icall(struct at_state_t *at_state) | |||
509 | return ICALL_IGNORE; | 504 | return ICALL_IGNORE; |
510 | } | 505 | } |
511 | if (at_state->str_var[STR_NMBR]) { | 506 | if (at_state->str_var[STR_NMBR]) { |
512 | strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR], | 507 | strlcpy(response.parm.setup.phone, at_state->str_var[STR_NMBR], |
513 | sizeof response.parm.setup.phone - 1); | 508 | sizeof response.parm.setup.phone); |
514 | response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0; | ||
515 | } else | 509 | } else |
516 | response.parm.setup.phone[0] = 0; | 510 | response.parm.setup.phone[0] = 0; |
517 | if (at_state->str_var[STR_ZCPN]) { | 511 | if (at_state->str_var[STR_ZCPN]) { |
518 | strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN], | 512 | strlcpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN], |
519 | sizeof response.parm.setup.eazmsn - 1); | 513 | sizeof response.parm.setup.eazmsn); |
520 | response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0; | ||
521 | } else | 514 | } else |
522 | response.parm.setup.eazmsn[0] = 0; | 515 | response.parm.setup.eazmsn[0] = 0; |
523 | 516 | ||
524 | if (!bcs) { | 517 | if (!bcs) { |
525 | dev_notice(cs->dev, "no channel for incoming call\n"); | 518 | dev_notice(cs->dev, "no channel for incoming call\n"); |
526 | response.command = ISDN_STAT_ICALLW; | 519 | response.command = ISDN_STAT_ICALLW; |
527 | response.arg = 0; //FIXME | 520 | response.arg = 0; |
528 | } else { | 521 | } else { |
529 | gig_dbg(DEBUG_CMD, "Sending ICALL"); | 522 | gig_dbg(DEBUG_CMD, "Sending ICALL"); |
530 | response.command = ISDN_STAT_ICALL; | 523 | response.command = ISDN_STAT_ICALL; |
531 | response.arg = bcs->channel; //FIXME | 524 | response.arg = bcs->channel; |
532 | } | 525 | } |
533 | response.driver = cs->myid; | 526 | response.driver = cs->myid; |
534 | retval = cs->iif.statcallb(&response); | 527 | retval = iif->statcallb(&response); |
535 | gig_dbg(DEBUG_CMD, "Response: %d", retval); | 528 | gig_dbg(DEBUG_CMD, "Response: %d", retval); |
536 | switch (retval) { | 529 | switch (retval) { |
537 | case 0: /* no takers */ | 530 | case 0: /* no takers */ |
@@ -560,16 +553,109 @@ int gigaset_isdn_icall(struct at_state_t *at_state) | |||
560 | } | 553 | } |
561 | } | 554 | } |
562 | 555 | ||
563 | /* Set Callback function pointer */ | 556 | /** |
564 | int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) | 557 | * gigaset_isdn_connD() - signal D channel connect |
558 | * @bcs: B channel descriptor structure. | ||
559 | * | ||
560 | * Called by main module to notify the LL that the D channel connection has | ||
561 | * been established. | ||
562 | */ | ||
563 | void gigaset_isdn_connD(struct bc_state *bcs) | ||
565 | { | 564 | { |
566 | isdn_if *iif = &cs->iif; | 565 | gig_dbg(DEBUG_CMD, "sending DCONN"); |
566 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); | ||
567 | } | ||
567 | 568 | ||
568 | gig_dbg(DEBUG_ANY, "Register driver capabilities to LL"); | 569 | /** |
570 | * gigaset_isdn_hupD() - signal D channel hangup | ||
571 | * @bcs: B channel descriptor structure. | ||
572 | * | ||
573 | * Called by main module to notify the LL that the D channel connection has | ||
574 | * been shut down. | ||
575 | */ | ||
576 | void gigaset_isdn_hupD(struct bc_state *bcs) | ||
577 | { | ||
578 | gig_dbg(DEBUG_CMD, "sending DHUP"); | ||
579 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); | ||
580 | } | ||
581 | |||
582 | /** | ||
583 | * gigaset_isdn_connB() - signal B channel connect | ||
584 | * @bcs: B channel descriptor structure. | ||
585 | * | ||
586 | * Called by main module to notify the LL that the B channel connection has | ||
587 | * been established. | ||
588 | */ | ||
589 | void gigaset_isdn_connB(struct bc_state *bcs) | ||
590 | { | ||
591 | gig_dbg(DEBUG_CMD, "sending BCONN"); | ||
592 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * gigaset_isdn_hupB() - signal B channel hangup | ||
597 | * @bcs: B channel descriptor structure. | ||
598 | * | ||
599 | * Called by main module to notify the LL that the B channel connection has | ||
600 | * been shut down. | ||
601 | */ | ||
602 | void gigaset_isdn_hupB(struct bc_state *bcs) | ||
603 | { | ||
604 | gig_dbg(DEBUG_CMD, "sending BHUP"); | ||
605 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); | ||
606 | } | ||
607 | |||
608 | /** | ||
609 | * gigaset_isdn_start() - signal device availability | ||
610 | * @cs: device descriptor structure. | ||
611 | * | ||
612 | * Called by main module to notify the LL that the device is available for | ||
613 | * use. | ||
614 | */ | ||
615 | void gigaset_isdn_start(struct cardstate *cs) | ||
616 | { | ||
617 | gig_dbg(DEBUG_CMD, "sending RUN"); | ||
618 | gigaset_i4l_cmd(cs, ISDN_STAT_RUN); | ||
619 | } | ||
620 | |||
621 | /** | ||
622 | * gigaset_isdn_stop() - signal device unavailability | ||
623 | * @cs: device descriptor structure. | ||
624 | * | ||
625 | * Called by main module to notify the LL that the device is no longer | ||
626 | * available for use. | ||
627 | */ | ||
628 | void gigaset_isdn_stop(struct cardstate *cs) | ||
629 | { | ||
630 | gig_dbg(DEBUG_CMD, "sending STOP"); | ||
631 | gigaset_i4l_cmd(cs, ISDN_STAT_STOP); | ||
632 | } | ||
633 | |||
634 | /** | ||
635 | * gigaset_isdn_register() - register to LL | ||
636 | * @cs: device descriptor structure. | ||
637 | * @isdnid: device name. | ||
638 | * | ||
639 | * Called by main module to register the device with the LL. | ||
640 | * | ||
641 | * Return value: 1 for success, 0 for failure | ||
642 | */ | ||
643 | int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) | ||
644 | { | ||
645 | isdn_if *iif; | ||
646 | |||
647 | pr_info("ISDN4Linux interface\n"); | ||
648 | |||
649 | iif = kmalloc(sizeof *iif, GFP_KERNEL); | ||
650 | if (!iif) { | ||
651 | pr_err("out of memory\n"); | ||
652 | return 0; | ||
653 | } | ||
569 | 654 | ||
570 | if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index) | 655 | if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index) |
571 | >= sizeof iif->id) { | 656 | >= sizeof iif->id) { |
572 | pr_err("ID too long: %s\n", isdnid); | 657 | pr_err("ID too long: %s\n", isdnid); |
658 | kfree(iif); | ||
573 | return 0; | 659 | return 0; |
574 | } | 660 | } |
575 | 661 | ||
@@ -593,9 +679,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) | |||
593 | 679 | ||
594 | if (!register_isdn(iif)) { | 680 | if (!register_isdn(iif)) { |
595 | pr_err("register_isdn failed\n"); | 681 | pr_err("register_isdn failed\n"); |
682 | kfree(iif); | ||
596 | return 0; | 683 | return 0; |
597 | } | 684 | } |
598 | 685 | ||
686 | cs->iif = iif; | ||
599 | cs->myid = iif->channels; /* Set my device id */ | 687 | cs->myid = iif->channels; /* Set my device id */ |
688 | cs->hw_hdr_len = HW_HDR_LEN; | ||
600 | return 1; | 689 | return 1; |
601 | } | 690 | } |
691 | |||
692 | /** | ||
693 | * gigaset_isdn_unregister() - unregister from LL | ||
694 | * @cs: device descriptor structure. | ||
695 | * | ||
696 | * Called by main module to unregister the device from the LL. | ||
697 | */ | ||
698 | void gigaset_isdn_unregister(struct cardstate *cs) | ||
699 | { | ||
700 | gig_dbg(DEBUG_CMD, "sending UNLOAD"); | ||
701 | gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); | ||
702 | kfree(cs->iif); | ||
703 | cs->iif = NULL; | ||
704 | } | ||
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 6a8e1384e7bd..577809c03aed 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c | |||
@@ -162,7 +162,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) | |||
162 | return -ENODEV; | 162 | return -ENODEV; |
163 | 163 | ||
164 | if (mutex_lock_interruptible(&cs->mutex)) | 164 | if (mutex_lock_interruptible(&cs->mutex)) |
165 | return -ERESTARTSYS; // FIXME -EINTR? | 165 | return -ERESTARTSYS; |
166 | tty->driver_data = cs; | 166 | tty->driver_data = cs; |
167 | 167 | ||
168 | ++cs->open_count; | 168 | ++cs->open_count; |
@@ -171,7 +171,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) | |||
171 | spin_lock_irqsave(&cs->lock, flags); | 171 | spin_lock_irqsave(&cs->lock, flags); |
172 | cs->tty = tty; | 172 | cs->tty = tty; |
173 | spin_unlock_irqrestore(&cs->lock, flags); | 173 | spin_unlock_irqrestore(&cs->lock, flags); |
174 | tty->low_latency = 1; //FIXME test | 174 | tty->low_latency = 1; |
175 | } | 175 | } |
176 | 176 | ||
177 | mutex_unlock(&cs->mutex); | 177 | mutex_unlock(&cs->mutex); |
@@ -228,7 +228,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, | |||
228 | gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); | 228 | gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); |
229 | 229 | ||
230 | if (mutex_lock_interruptible(&cs->mutex)) | 230 | if (mutex_lock_interruptible(&cs->mutex)) |
231 | return -ERESTARTSYS; // FIXME -EINTR? | 231 | return -ERESTARTSYS; |
232 | 232 | ||
233 | if (!cs->connected) { | 233 | if (!cs->connected) { |
234 | gig_dbg(DEBUG_IF, "not connected"); | 234 | gig_dbg(DEBUG_IF, "not connected"); |
@@ -299,9 +299,8 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file) | |||
299 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); | 299 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); |
300 | 300 | ||
301 | if (mutex_lock_interruptible(&cs->mutex)) | 301 | if (mutex_lock_interruptible(&cs->mutex)) |
302 | return -ERESTARTSYS; // FIXME -EINTR? | 302 | return -ERESTARTSYS; |
303 | 303 | ||
304 | // FIXME read from device? | ||
305 | retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); | 304 | retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); |
306 | 305 | ||
307 | mutex_unlock(&cs->mutex); | 306 | mutex_unlock(&cs->mutex); |
@@ -326,7 +325,7 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file, | |||
326 | cs->minor_index, __func__, set, clear); | 325 | cs->minor_index, __func__, set, clear); |
327 | 326 | ||
328 | if (mutex_lock_interruptible(&cs->mutex)) | 327 | if (mutex_lock_interruptible(&cs->mutex)) |
329 | return -ERESTARTSYS; // FIXME -EINTR? | 328 | return -ERESTARTSYS; |
330 | 329 | ||
331 | if (!cs->connected) { | 330 | if (!cs->connected) { |
332 | gig_dbg(DEBUG_IF, "not connected"); | 331 | gig_dbg(DEBUG_IF, "not connected"); |
@@ -356,7 +355,7 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
356 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); | 355 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); |
357 | 356 | ||
358 | if (mutex_lock_interruptible(&cs->mutex)) | 357 | if (mutex_lock_interruptible(&cs->mutex)) |
359 | return -ERESTARTSYS; // FIXME -EINTR? | 358 | return -ERESTARTSYS; |
360 | 359 | ||
361 | if (!cs->connected) { | 360 | if (!cs->connected) { |
362 | gig_dbg(DEBUG_IF, "not connected"); | 361 | gig_dbg(DEBUG_IF, "not connected"); |
@@ -390,7 +389,7 @@ static int if_write_room(struct tty_struct *tty) | |||
390 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); | 389 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); |
391 | 390 | ||
392 | if (mutex_lock_interruptible(&cs->mutex)) | 391 | if (mutex_lock_interruptible(&cs->mutex)) |
393 | return -ERESTARTSYS; // FIXME -EINTR? | 392 | return -ERESTARTSYS; |
394 | 393 | ||
395 | if (!cs->connected) { | 394 | if (!cs->connected) { |
396 | gig_dbg(DEBUG_IF, "not connected"); | 395 | gig_dbg(DEBUG_IF, "not connected"); |
@@ -455,9 +454,8 @@ static void if_throttle(struct tty_struct *tty) | |||
455 | gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ | 454 | gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ |
456 | else if (!cs->open_count) | 455 | else if (!cs->open_count) |
457 | dev_warn(cs->dev, "%s: device not opened\n", __func__); | 456 | dev_warn(cs->dev, "%s: device not opened\n", __func__); |
458 | else { | 457 | else |
459 | //FIXME | 458 | gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); |
460 | } | ||
461 | 459 | ||
462 | mutex_unlock(&cs->mutex); | 460 | mutex_unlock(&cs->mutex); |
463 | } | 461 | } |
@@ -480,9 +478,8 @@ static void if_unthrottle(struct tty_struct *tty) | |||
480 | gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ | 478 | gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ |
481 | else if (!cs->open_count) | 479 | else if (!cs->open_count) |
482 | dev_warn(cs->dev, "%s: device not opened\n", __func__); | 480 | dev_warn(cs->dev, "%s: device not opened\n", __func__); |
483 | else { | 481 | else |
484 | //FIXME | 482 | gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); |
485 | } | ||
486 | 483 | ||
487 | mutex_unlock(&cs->mutex); | 484 | mutex_unlock(&cs->mutex); |
488 | } | 485 | } |
@@ -515,10 +512,9 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
515 | goto out; | 512 | goto out; |
516 | } | 513 | } |
517 | 514 | ||
518 | // stolen from mct_u232.c | ||
519 | iflag = tty->termios->c_iflag; | 515 | iflag = tty->termios->c_iflag; |
520 | cflag = tty->termios->c_cflag; | 516 | cflag = tty->termios->c_cflag; |
521 | old_cflag = old ? old->c_cflag : cflag; //FIXME? | 517 | old_cflag = old ? old->c_cflag : cflag; |
522 | gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", | 518 | gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", |
523 | cs->minor_index, iflag, cflag, old_cflag); | 519 | cs->minor_index, iflag, cflag, old_cflag); |
524 | 520 | ||
@@ -632,7 +628,8 @@ void gigaset_if_receive(struct cardstate *cs, | |||
632 | struct tty_struct *tty; | 628 | struct tty_struct *tty; |
633 | 629 | ||
634 | spin_lock_irqsave(&cs->lock, flags); | 630 | spin_lock_irqsave(&cs->lock, flags); |
635 | if ((tty = cs->tty) == NULL) | 631 | tty = cs->tty; |
632 | if (tty == NULL) | ||
636 | gig_dbg(DEBUG_ANY, "receive on closed device"); | 633 | gig_dbg(DEBUG_ANY, "receive on closed device"); |
637 | else { | 634 | else { |
638 | tty_buffer_request_room(tty, len); | 635 | tty_buffer_request_room(tty, len); |
@@ -659,9 +656,9 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, | |||
659 | 656 | ||
660 | drv->have_tty = 0; | 657 | drv->have_tty = 0; |
661 | 658 | ||
662 | if ((drv->tty = alloc_tty_driver(minors)) == NULL) | 659 | drv->tty = tty = alloc_tty_driver(minors); |
660 | if (tty == NULL) | ||
663 | goto enomem; | 661 | goto enomem; |
664 | tty = drv->tty; | ||
665 | 662 | ||
666 | tty->magic = TTY_DRIVER_MAGIC, | 663 | tty->magic = TTY_DRIVER_MAGIC, |
667 | tty->major = GIG_MAJOR, | 664 | tty->major = GIG_MAJOR, |
@@ -676,8 +673,8 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, | |||
676 | 673 | ||
677 | tty->owner = THIS_MODULE; | 674 | tty->owner = THIS_MODULE; |
678 | 675 | ||
679 | tty->init_termios = tty_std_termios; //FIXME | 676 | tty->init_termios = tty_std_termios; |
680 | tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //FIXME | 677 | tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
681 | tty_set_operations(tty, &if_ops); | 678 | tty_set_operations(tty, &if_ops); |
682 | 679 | ||
683 | ret = tty_register_driver(tty); | 680 | ret = tty_register_driver(tty); |
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 9f3ef7b4248c..85394a6ebae8 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c | |||
@@ -41,7 +41,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) | |||
41 | 41 | ||
42 | read = iwb->read; | 42 | read = iwb->read; |
43 | write = iwb->write; | 43 | write = iwb->write; |
44 | if ((freebytes = read - write) > 0) { | 44 | freebytes = read - write; |
45 | if (freebytes > 0) { | ||
45 | /* no wraparound: need padding space within regular area */ | 46 | /* no wraparound: need padding space within regular area */ |
46 | return freebytes - BAS_OUTBUFPAD; | 47 | return freebytes - BAS_OUTBUFPAD; |
47 | } else if (read < BAS_OUTBUFPAD) { | 48 | } else if (read < BAS_OUTBUFPAD) { |
@@ -53,29 +54,6 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) | |||
53 | } | 54 | } |
54 | } | 55 | } |
55 | 56 | ||
56 | /* compare two offsets within the buffer | ||
57 | * The buffer is seen as circular, with the read position as start | ||
58 | * returns -1/0/1 if position a </=/> position b without crossing 'read' | ||
59 | */ | ||
60 | static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b) | ||
61 | { | ||
62 | int read; | ||
63 | if (a == b) | ||
64 | return 0; | ||
65 | read = iwb->read; | ||
66 | if (a < b) { | ||
67 | if (a < read && read <= b) | ||
68 | return +1; | ||
69 | else | ||
70 | return -1; | ||
71 | } else { | ||
72 | if (b < read && read <= a) | ||
73 | return -1; | ||
74 | else | ||
75 | return +1; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /* start writing | 57 | /* start writing |
80 | * acquire the write semaphore | 58 | * acquire the write semaphore |
81 | * return true if acquired, false if busy | 59 | * return true if acquired, false if busy |
@@ -271,7 +249,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag, | |||
271 | * bit 14..13 = number of bits added by stuffing | 249 | * bit 14..13 = number of bits added by stuffing |
272 | */ | 250 | */ |
273 | static const u16 stufftab[5 * 256] = { | 251 | static const u16 stufftab[5 * 256] = { |
274 | // previous 1s = 0: | 252 | /* previous 1s = 0: */ |
275 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, | 253 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, |
276 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, | 254 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, |
277 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, | 255 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, |
@@ -289,7 +267,7 @@ static const u16 stufftab[5 * 256] = { | |||
289 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef, | 267 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef, |
290 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf, | 268 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf, |
291 | 269 | ||
292 | // previous 1s = 1: | 270 | /* previous 1s = 1: */ |
293 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f, | 271 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f, |
294 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f, | 272 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f, |
295 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f, | 273 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f, |
@@ -307,7 +285,7 @@ static const u16 stufftab[5 * 256] = { | |||
307 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf, | 285 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf, |
308 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef, | 286 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef, |
309 | 287 | ||
310 | // previous 1s = 2: | 288 | /* previous 1s = 2: */ |
311 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017, | 289 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017, |
312 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037, | 290 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037, |
313 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057, | 291 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057, |
@@ -325,7 +303,7 @@ static const u16 stufftab[5 * 256] = { | |||
325 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7, | 303 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7, |
326 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7, | 304 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7, |
327 | 305 | ||
328 | // previous 1s = 3: | 306 | /* previous 1s = 3: */ |
329 | 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b, | 307 | 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b, |
330 | 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b, | 308 | 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b, |
331 | 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b, | 309 | 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b, |
@@ -343,7 +321,7 @@ static const u16 stufftab[5 * 256] = { | |||
343 | 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb, | 321 | 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb, |
344 | 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb, | 322 | 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb, |
345 | 323 | ||
346 | // previous 1s = 4: | 324 | /* previous 1s = 4: */ |
347 | 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d, | 325 | 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d, |
348 | 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d, | 326 | 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d, |
349 | 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d, | 327 | 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d, |
@@ -367,7 +345,8 @@ static const u16 stufftab[5 * 256] = { | |||
367 | * parameters: | 345 | * parameters: |
368 | * cin input byte | 346 | * cin input byte |
369 | * ones number of trailing '1' bits in result before this step | 347 | * ones number of trailing '1' bits in result before this step |
370 | * iwb pointer to output buffer structure (write semaphore must be held) | 348 | * iwb pointer to output buffer structure |
349 | * (write semaphore must be held) | ||
371 | * return value: | 350 | * return value: |
372 | * number of trailing '1' bits in result after this step | 351 | * number of trailing '1' bits in result after this step |
373 | */ | 352 | */ |
@@ -408,7 +387,8 @@ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, | |||
408 | * parameters: | 387 | * parameters: |
409 | * in input buffer | 388 | * in input buffer |
410 | * count number of bytes in input buffer | 389 | * count number of bytes in input buffer |
411 | * iwb pointer to output buffer structure (write semaphore must be held) | 390 | * iwb pointer to output buffer structure |
391 | * (write semaphore must be held) | ||
412 | * return value: | 392 | * return value: |
413 | * position of end of packet in output buffer on success, | 393 | * position of end of packet in output buffer on success, |
414 | * -EAGAIN if write semaphore busy or buffer full | 394 | * -EAGAIN if write semaphore busy or buffer full |
@@ -440,7 +420,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, | |||
440 | fcs = crc_ccitt_byte(fcs, c); | 420 | fcs = crc_ccitt_byte(fcs, c); |
441 | } | 421 | } |
442 | 422 | ||
443 | /* bitstuff and append FCS (complemented, least significant byte first) */ | 423 | /* bitstuff and append FCS |
424 | * (complemented, least significant byte first) */ | ||
444 | fcs ^= 0xffff; | 425 | fcs ^= 0xffff; |
445 | ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones); | 426 | ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones); |
446 | ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones); | 427 | ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones); |
@@ -459,7 +440,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, | |||
459 | * parameters: | 440 | * parameters: |
460 | * in input buffer | 441 | * in input buffer |
461 | * count number of bytes in input buffer | 442 | * count number of bytes in input buffer |
462 | * iwb pointer to output buffer structure (write semaphore must be held) | 443 | * iwb pointer to output buffer structure |
444 | * (write semaphore must be held) | ||
463 | * return value: | 445 | * return value: |
464 | * position of end of packet in output buffer on success, | 446 | * position of end of packet in output buffer on success, |
465 | * -EAGAIN if write semaphore busy or buffer full | 447 | * -EAGAIN if write semaphore busy or buffer full |
@@ -500,7 +482,7 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) | |||
500 | int result; | 482 | int result; |
501 | 483 | ||
502 | switch (bcs->proto2) { | 484 | switch (bcs->proto2) { |
503 | case ISDN_PROTO_L2_HDLC: | 485 | case L2_HDLC: |
504 | result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); | 486 | result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); |
505 | gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", | 487 | gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", |
506 | __func__, len, result); | 488 | __func__, len, result); |
@@ -542,8 +524,9 @@ static inline void hdlc_flush(struct bc_state *bcs) | |||
542 | if (likely(bcs->skb != NULL)) | 524 | if (likely(bcs->skb != NULL)) |
543 | skb_trim(bcs->skb, 0); | 525 | skb_trim(bcs->skb, 0); |
544 | else if (!bcs->ignore) { | 526 | else if (!bcs->ignore) { |
545 | if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | 527 | bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len); |
546 | skb_reserve(bcs->skb, HW_HDR_LEN); | 528 | if (bcs->skb) |
529 | skb_reserve(bcs->skb, bcs->cs->hw_hdr_len); | ||
547 | else | 530 | else |
548 | dev_err(bcs->cs->dev, "could not allocate skb\n"); | 531 | dev_err(bcs->cs->dev, "could not allocate skb\n"); |
549 | } | 532 | } |
@@ -557,43 +540,46 @@ static inline void hdlc_flush(struct bc_state *bcs) | |||
557 | */ | 540 | */ |
558 | static inline void hdlc_done(struct bc_state *bcs) | 541 | static inline void hdlc_done(struct bc_state *bcs) |
559 | { | 542 | { |
543 | struct cardstate *cs = bcs->cs; | ||
560 | struct sk_buff *procskb; | 544 | struct sk_buff *procskb; |
545 | unsigned int len; | ||
561 | 546 | ||
562 | if (unlikely(bcs->ignore)) { | 547 | if (unlikely(bcs->ignore)) { |
563 | bcs->ignore--; | 548 | bcs->ignore--; |
564 | hdlc_flush(bcs); | 549 | hdlc_flush(bcs); |
565 | return; | 550 | return; |
566 | } | 551 | } |
567 | 552 | procskb = bcs->skb; | |
568 | if ((procskb = bcs->skb) == NULL) { | 553 | if (procskb == NULL) { |
569 | /* previous error */ | 554 | /* previous error */ |
570 | gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); | 555 | gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); |
571 | gigaset_rcv_error(NULL, bcs->cs, bcs); | 556 | gigaset_isdn_rcv_err(bcs); |
572 | } else if (procskb->len < 2) { | 557 | } else if (procskb->len < 2) { |
573 | dev_notice(bcs->cs->dev, "received short frame (%d octets)\n", | 558 | dev_notice(cs->dev, "received short frame (%d octets)\n", |
574 | procskb->len); | 559 | procskb->len); |
575 | bcs->hw.bas->runts++; | 560 | bcs->hw.bas->runts++; |
576 | gigaset_rcv_error(procskb, bcs->cs, bcs); | 561 | dev_kfree_skb_any(procskb); |
562 | gigaset_isdn_rcv_err(bcs); | ||
577 | } else if (bcs->fcs != PPP_GOODFCS) { | 563 | } else if (bcs->fcs != PPP_GOODFCS) { |
578 | dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n", | 564 | dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); |
579 | bcs->fcs); | ||
580 | bcs->hw.bas->fcserrs++; | 565 | bcs->hw.bas->fcserrs++; |
581 | gigaset_rcv_error(procskb, bcs->cs, bcs); | 566 | dev_kfree_skb_any(procskb); |
567 | gigaset_isdn_rcv_err(bcs); | ||
582 | } else { | 568 | } else { |
583 | procskb->len -= 2; /* subtract FCS */ | 569 | len = procskb->len; |
584 | procskb->tail -= 2; | 570 | __skb_trim(procskb, len -= 2); /* subtract FCS */ |
585 | gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", | 571 | gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, len); |
586 | __func__, procskb->len); | ||
587 | dump_bytes(DEBUG_STREAM_DUMP, | 572 | dump_bytes(DEBUG_STREAM_DUMP, |
588 | "rcv data", procskb->data, procskb->len); | 573 | "rcv data", procskb->data, len); |
589 | bcs->hw.bas->goodbytes += procskb->len; | 574 | bcs->hw.bas->goodbytes += len; |
590 | gigaset_rcv_skb(procskb, bcs->cs, bcs); | 575 | gigaset_skb_rcvd(bcs, procskb); |
591 | } | 576 | } |
592 | 577 | ||
593 | if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | 578 | bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); |
594 | skb_reserve(bcs->skb, HW_HDR_LEN); | 579 | if (bcs->skb) |
580 | skb_reserve(bcs->skb, cs->hw_hdr_len); | ||
595 | else | 581 | else |
596 | dev_err(bcs->cs->dev, "could not allocate skb\n"); | 582 | dev_err(cs->dev, "could not allocate skb\n"); |
597 | bcs->fcs = PPP_INITFCS; | 583 | bcs->fcs = PPP_INITFCS; |
598 | } | 584 | } |
599 | 585 | ||
@@ -610,12 +596,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) | |||
610 | 596 | ||
611 | dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); | 597 | dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); |
612 | bcs->hw.bas->alignerrs++; | 598 | bcs->hw.bas->alignerrs++; |
613 | gigaset_rcv_error(bcs->skb, bcs->cs, bcs); | 599 | gigaset_isdn_rcv_err(bcs); |
614 | 600 | __skb_trim(bcs->skb, 0); | |
615 | if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | ||
616 | skb_reserve(bcs->skb, HW_HDR_LEN); | ||
617 | else | ||
618 | dev_err(bcs->cs->dev, "could not allocate skb\n"); | ||
619 | bcs->fcs = PPP_INITFCS; | 601 | bcs->fcs = PPP_INITFCS; |
620 | } | 602 | } |
621 | 603 | ||
@@ -646,10 +628,10 @@ static const unsigned char bitcounts[256] = { | |||
646 | }; | 628 | }; |
647 | 629 | ||
648 | /* hdlc_unpack | 630 | /* hdlc_unpack |
649 | * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation) | 631 | * perform HDLC frame processing (bit unstuffing, flag detection, FCS |
650 | * on a sequence of received data bytes (8 bits each, LSB first) | 632 | * calculation) on a sequence of received data bytes (8 bits each, LSB first) |
651 | * pass on successfully received, complete frames as SKBs via gigaset_rcv_skb | 633 | * pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd |
652 | * notify of errors via gigaset_rcv_error | 634 | * notify of errors via gigaset_isdn_rcv_err |
653 | * tally frames, errors etc. in BC structure counters | 635 | * tally frames, errors etc. in BC structure counters |
654 | * parameters: | 636 | * parameters: |
655 | * src received data | 637 | * src received data |
@@ -665,9 +647,12 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
665 | 647 | ||
666 | /* load previous state: | 648 | /* load previous state: |
667 | * inputstate = set of flag bits: | 649 | * inputstate = set of flag bits: |
668 | * - INS_flag_hunt: no complete opening flag received since connection setup or last abort | 650 | * - INS_flag_hunt: no complete opening flag received since connection |
669 | * - INS_have_data: at least one complete data byte received since last flag | 651 | * setup or last abort |
670 | * seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7) | 652 | * - INS_have_data: at least one complete data byte received since last |
653 | * flag | ||
654 | * seqlen = number of consecutive '1' bits in last 7 input stream bits | ||
655 | * (0..7) | ||
671 | * inbyte = accumulated partial data byte (if !INS_flag_hunt) | 656 | * inbyte = accumulated partial data byte (if !INS_flag_hunt) |
672 | * inbits = number of valid bits in inbyte, starting at LSB (0..6) | 657 | * inbits = number of valid bits in inbyte, starting at LSB (0..6) |
673 | */ | 658 | */ |
@@ -701,9 +686,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
701 | inbyte = c >> (lead1 + 1); | 686 | inbyte = c >> (lead1 + 1); |
702 | inbits = 7 - lead1; | 687 | inbits = 7 - lead1; |
703 | if (trail1 >= 8) { | 688 | if (trail1 >= 8) { |
704 | /* interior stuffing: omitting the MSB handles most cases */ | 689 | /* interior stuffing: |
690 | * omitting the MSB handles most cases, | ||
691 | * correct the incorrectly handled | ||
692 | * cases individually */ | ||
705 | inbits--; | 693 | inbits--; |
706 | /* correct the incorrectly handled cases individually */ | ||
707 | switch (c) { | 694 | switch (c) { |
708 | case 0xbe: | 695 | case 0xbe: |
709 | inbyte = 0x3f; | 696 | inbyte = 0x3f; |
@@ -729,13 +716,14 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
729 | hdlc_flush(bcs); | 716 | hdlc_flush(bcs); |
730 | inputstate |= INS_flag_hunt; | 717 | inputstate |= INS_flag_hunt; |
731 | } else if (seqlen == 6) { | 718 | } else if (seqlen == 6) { |
732 | /* closing flag, including (6 - lead1) '1's and one '0' from inbits */ | 719 | /* closing flag, including (6 - lead1) '1's |
720 | * and one '0' from inbits */ | ||
733 | if (inbits > 7 - lead1) { | 721 | if (inbits > 7 - lead1) { |
734 | hdlc_frag(bcs, inbits + lead1 - 7); | 722 | hdlc_frag(bcs, inbits + lead1 - 7); |
735 | inputstate &= ~INS_have_data; | 723 | inputstate &= ~INS_have_data; |
736 | } else { | 724 | } else { |
737 | if (inbits < 7 - lead1) | 725 | if (inbits < 7 - lead1) |
738 | ubc->stolen0s ++; | 726 | ubc->stolen0s++; |
739 | if (inputstate & INS_have_data) { | 727 | if (inputstate & INS_have_data) { |
740 | hdlc_done(bcs); | 728 | hdlc_done(bcs); |
741 | inputstate &= ~INS_have_data; | 729 | inputstate &= ~INS_have_data; |
@@ -744,7 +732,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
744 | 732 | ||
745 | if (c == PPP_FLAG) { | 733 | if (c == PPP_FLAG) { |
746 | /* complete flag, LSB overlaps preceding flag */ | 734 | /* complete flag, LSB overlaps preceding flag */ |
747 | ubc->shared0s ++; | 735 | ubc->shared0s++; |
748 | inbits = 0; | 736 | inbits = 0; |
749 | inbyte = 0; | 737 | inbyte = 0; |
750 | } else if (trail1 != 7) { | 738 | } else if (trail1 != 7) { |
@@ -752,9 +740,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
752 | inbyte = c >> (lead1 + 1); | 740 | inbyte = c >> (lead1 + 1); |
753 | inbits = 7 - lead1; | 741 | inbits = 7 - lead1; |
754 | if (trail1 >= 8) { | 742 | if (trail1 >= 8) { |
755 | /* interior stuffing: omitting the MSB handles most cases */ | 743 | /* interior stuffing: |
744 | * omitting the MSB handles most cases, | ||
745 | * correct the incorrectly handled | ||
746 | * cases individually */ | ||
756 | inbits--; | 747 | inbits--; |
757 | /* correct the incorrectly handled cases individually */ | ||
758 | switch (c) { | 748 | switch (c) { |
759 | case 0xbe: | 749 | case 0xbe: |
760 | inbyte = 0x3f; | 750 | inbyte = 0x3f; |
@@ -762,7 +752,8 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
762 | } | 752 | } |
763 | } | 753 | } |
764 | } else { | 754 | } else { |
765 | /* abort sequence follows, skb already empty anyway */ | 755 | /* abort sequence follows, |
756 | * skb already empty anyway */ | ||
766 | ubc->aborts++; | 757 | ubc->aborts++; |
767 | inputstate |= INS_flag_hunt; | 758 | inputstate |= INS_flag_hunt; |
768 | } | 759 | } |
@@ -787,14 +778,17 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
787 | } else { | 778 | } else { |
788 | /* stuffed data */ | 779 | /* stuffed data */ |
789 | if (trail1 < 7) { /* => seqlen == 5 */ | 780 | if (trail1 < 7) { /* => seqlen == 5 */ |
790 | /* stuff bit at position lead1, no interior stuffing */ | 781 | /* stuff bit at position lead1, |
782 | * no interior stuffing */ | ||
791 | unsigned char mask = (1 << lead1) - 1; | 783 | unsigned char mask = (1 << lead1) - 1; |
792 | c = (c & mask) | ((c & ~mask) >> 1); | 784 | c = (c & mask) | ((c & ~mask) >> 1); |
793 | inbyte |= c << inbits; | 785 | inbyte |= c << inbits; |
794 | inbits += 7; | 786 | inbits += 7; |
795 | } else if (seqlen < 5) { /* trail1 >= 8 */ | 787 | } else if (seqlen < 5) { /* trail1 >= 8 */ |
796 | /* interior stuffing: omitting the MSB handles most cases */ | 788 | /* interior stuffing: |
797 | /* correct the incorrectly handled cases individually */ | 789 | * omitting the MSB handles most cases, |
790 | * correct the incorrectly handled | ||
791 | * cases individually */ | ||
798 | switch (c) { | 792 | switch (c) { |
799 | case 0xbe: | 793 | case 0xbe: |
800 | c = 0x7e; | 794 | c = 0x7e; |
@@ -804,8 +798,9 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
804 | inbits += 7; | 798 | inbits += 7; |
805 | } else { /* seqlen == 5 && trail1 >= 8 */ | 799 | } else { /* seqlen == 5 && trail1 >= 8 */ |
806 | 800 | ||
807 | /* stuff bit at lead1 *and* interior stuffing */ | 801 | /* stuff bit at lead1 *and* interior |
808 | switch (c) { /* unstuff individually */ | 802 | * stuffing -- unstuff individually */ |
803 | switch (c) { | ||
809 | case 0x7d: | 804 | case 0x7d: |
810 | c = 0x3f; | 805 | c = 0x3f; |
811 | break; | 806 | break; |
@@ -841,7 +836,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
841 | } | 836 | } |
842 | 837 | ||
843 | /* trans_receive | 838 | /* trans_receive |
844 | * pass on received USB frame transparently as SKB via gigaset_rcv_skb | 839 | * pass on received USB frame transparently as SKB via gigaset_skb_rcvd |
845 | * invert bytes | 840 | * invert bytes |
846 | * tally frames, errors etc. in BC structure counters | 841 | * tally frames, errors etc. in BC structure counters |
847 | * parameters: | 842 | * parameters: |
@@ -852,6 +847,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
852 | static inline void trans_receive(unsigned char *src, unsigned count, | 847 | static inline void trans_receive(unsigned char *src, unsigned count, |
853 | struct bc_state *bcs) | 848 | struct bc_state *bcs) |
854 | { | 849 | { |
850 | struct cardstate *cs = bcs->cs; | ||
855 | struct sk_buff *skb; | 851 | struct sk_buff *skb; |
856 | int dobytes; | 852 | int dobytes; |
857 | unsigned char *dst; | 853 | unsigned char *dst; |
@@ -861,13 +857,14 @@ static inline void trans_receive(unsigned char *src, unsigned count, | |||
861 | hdlc_flush(bcs); | 857 | hdlc_flush(bcs); |
862 | return; | 858 | return; |
863 | } | 859 | } |
864 | if (unlikely((skb = bcs->skb) == NULL)) { | 860 | skb = bcs->skb; |
865 | bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); | 861 | if (unlikely(skb == NULL)) { |
862 | bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); | ||
866 | if (!skb) { | 863 | if (!skb) { |
867 | dev_err(bcs->cs->dev, "could not allocate skb\n"); | 864 | dev_err(cs->dev, "could not allocate skb\n"); |
868 | return; | 865 | return; |
869 | } | 866 | } |
870 | skb_reserve(skb, HW_HDR_LEN); | 867 | skb_reserve(skb, cs->hw_hdr_len); |
871 | } | 868 | } |
872 | bcs->hw.bas->goodbytes += skb->len; | 869 | bcs->hw.bas->goodbytes += skb->len; |
873 | dobytes = TRANSBUFSIZE - skb->len; | 870 | dobytes = TRANSBUFSIZE - skb->len; |
@@ -881,23 +878,24 @@ static inline void trans_receive(unsigned char *src, unsigned count, | |||
881 | if (dobytes == 0) { | 878 | if (dobytes == 0) { |
882 | dump_bytes(DEBUG_STREAM_DUMP, | 879 | dump_bytes(DEBUG_STREAM_DUMP, |
883 | "rcv data", skb->data, skb->len); | 880 | "rcv data", skb->data, skb->len); |
884 | gigaset_rcv_skb(skb, bcs->cs, bcs); | 881 | gigaset_skb_rcvd(bcs, skb); |
885 | bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); | 882 | bcs->skb = skb = |
883 | dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); | ||
886 | if (!skb) { | 884 | if (!skb) { |
887 | dev_err(bcs->cs->dev, | 885 | dev_err(cs->dev, "could not allocate skb\n"); |
888 | "could not allocate skb\n"); | ||
889 | return; | 886 | return; |
890 | } | 887 | } |
891 | skb_reserve(bcs->skb, HW_HDR_LEN); | 888 | skb_reserve(skb, cs->hw_hdr_len); |
892 | dobytes = TRANSBUFSIZE; | 889 | dobytes = TRANSBUFSIZE; |
893 | } | 890 | } |
894 | } | 891 | } |
895 | } | 892 | } |
896 | 893 | ||
897 | void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs) | 894 | void gigaset_isoc_receive(unsigned char *src, unsigned count, |
895 | struct bc_state *bcs) | ||
898 | { | 896 | { |
899 | switch (bcs->proto2) { | 897 | switch (bcs->proto2) { |
900 | case ISDN_PROTO_L2_HDLC: | 898 | case L2_HDLC: |
901 | hdlc_unpack(src, count, bcs); | 899 | hdlc_unpack(src, count, bcs); |
902 | break; | 900 | break; |
903 | default: /* assume transparent */ | 901 | default: /* assume transparent */ |
@@ -981,8 +979,10 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) | |||
981 | * @bcs: B channel descriptor structure. | 979 | * @bcs: B channel descriptor structure. |
982 | * @skb: data to send. | 980 | * @skb: data to send. |
983 | * | 981 | * |
984 | * Called by i4l.c to queue an skb for sending, and start transmission if | 982 | * Called by LL to queue an skb for sending, and start transmission if |
985 | * necessary. | 983 | * necessary. |
984 | * Once the payload data has been transmitted completely, gigaset_skb_sent() | ||
985 | * will be called with the skb's link layer header preserved. | ||
986 | * | 986 | * |
987 | * Return value: | 987 | * Return value: |
988 | * number of bytes accepted for sending (skb->len) if ok, | 988 | * number of bytes accepted for sending (skb->len) if ok, |
diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index 9715aad9c3f0..758a00c1d2e2 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c | |||
@@ -39,7 +39,7 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, | |||
39 | return -EINVAL; | 39 | return -EINVAL; |
40 | 40 | ||
41 | if (mutex_lock_interruptible(&cs->mutex)) | 41 | if (mutex_lock_interruptible(&cs->mutex)) |
42 | return -ERESTARTSYS; // FIXME -EINTR? | 42 | return -ERESTARTSYS; |
43 | 43 | ||
44 | cs->waiting = 1; | 44 | cs->waiting = 1; |
45 | if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, | 45 | if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, |
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 3071a52467ed..ac3409ea5d99 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c | |||
@@ -164,9 +164,15 @@ static void gigaset_modem_fill(unsigned long data) | |||
164 | { | 164 | { |
165 | struct cardstate *cs = (struct cardstate *) data; | 165 | struct cardstate *cs = (struct cardstate *) data; |
166 | struct bc_state *bcs; | 166 | struct bc_state *bcs; |
167 | struct sk_buff *nextskb; | ||
167 | int sent = 0; | 168 | int sent = 0; |
168 | 169 | ||
169 | if (!cs || !(bcs = cs->bcs)) { | 170 | if (!cs) { |
171 | gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); | ||
172 | return; | ||
173 | } | ||
174 | bcs = cs->bcs; | ||
175 | if (!bcs) { | ||
170 | gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); | 176 | gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); |
171 | return; | 177 | return; |
172 | } | 178 | } |
@@ -179,9 +185,11 @@ static void gigaset_modem_fill(unsigned long data) | |||
179 | return; | 185 | return; |
180 | 186 | ||
181 | /* no command to send; get skb */ | 187 | /* no command to send; get skb */ |
182 | if (!(bcs->tx_skb = skb_dequeue(&bcs->squeue))) | 188 | nextskb = skb_dequeue(&bcs->squeue); |
189 | if (!nextskb) | ||
183 | /* no skb either, nothing to do */ | 190 | /* no skb either, nothing to do */ |
184 | return; | 191 | return; |
192 | bcs->tx_skb = nextskb; | ||
185 | 193 | ||
186 | gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)", | 194 | gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)", |
187 | (unsigned long) bcs->tx_skb); | 195 | (unsigned long) bcs->tx_skb); |
@@ -236,19 +244,20 @@ static void flush_send_queue(struct cardstate *cs) | |||
236 | * number of bytes queued, or error code < 0 | 244 | * number of bytes queued, or error code < 0 |
237 | */ | 245 | */ |
238 | static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | 246 | static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, |
239 | int len, struct tasklet_struct *wake_tasklet) | 247 | int len, struct tasklet_struct *wake_tasklet) |
240 | { | 248 | { |
241 | struct cmdbuf_t *cb; | 249 | struct cmdbuf_t *cb; |
242 | unsigned long flags; | 250 | unsigned long flags; |
243 | 251 | ||
244 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? | 252 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
245 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 253 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
246 | "CMD Transmit", len, buf); | 254 | "CMD Transmit", len, buf); |
247 | 255 | ||
248 | if (len <= 0) | 256 | if (len <= 0) |
249 | return 0; | 257 | return 0; |
250 | 258 | ||
251 | if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { | 259 | cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); |
260 | if (!cb) { | ||
252 | dev_err(cs->dev, "%s: out of memory!\n", __func__); | 261 | dev_err(cs->dev, "%s: out of memory!\n", __func__); |
253 | return -ENOMEM; | 262 | return -ENOMEM; |
254 | } | 263 | } |
@@ -392,7 +401,6 @@ static void gigaset_device_release(struct device *dev) | |||
392 | struct platform_device *pdev = to_platform_device(dev); | 401 | struct platform_device *pdev = to_platform_device(dev); |
393 | 402 | ||
394 | /* adapted from platform_device_release() in drivers/base/platform.c */ | 403 | /* adapted from platform_device_release() in drivers/base/platform.c */ |
395 | //FIXME is this actually necessary? | ||
396 | kfree(dev->platform_data); | 404 | kfree(dev->platform_data); |
397 | kfree(pdev->resource); | 405 | kfree(pdev->resource); |
398 | } | 406 | } |
@@ -404,16 +412,20 @@ static void gigaset_device_release(struct device *dev) | |||
404 | static int gigaset_initcshw(struct cardstate *cs) | 412 | static int gigaset_initcshw(struct cardstate *cs) |
405 | { | 413 | { |
406 | int rc; | 414 | int rc; |
415 | struct ser_cardstate *scs; | ||
407 | 416 | ||
408 | if (!(cs->hw.ser = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL))) { | 417 | scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL); |
418 | if (!scs) { | ||
409 | pr_err("out of memory\n"); | 419 | pr_err("out of memory\n"); |
410 | return 0; | 420 | return 0; |
411 | } | 421 | } |
422 | cs->hw.ser = scs; | ||
412 | 423 | ||
413 | cs->hw.ser->dev.name = GIGASET_MODULENAME; | 424 | cs->hw.ser->dev.name = GIGASET_MODULENAME; |
414 | cs->hw.ser->dev.id = cs->minor_index; | 425 | cs->hw.ser->dev.id = cs->minor_index; |
415 | cs->hw.ser->dev.dev.release = gigaset_device_release; | 426 | cs->hw.ser->dev.dev.release = gigaset_device_release; |
416 | if ((rc = platform_device_register(&cs->hw.ser->dev)) != 0) { | 427 | rc = platform_device_register(&cs->hw.ser->dev); |
428 | if (rc != 0) { | ||
417 | pr_err("error %d registering platform device\n", rc); | 429 | pr_err("error %d registering platform device\n", rc); |
418 | kfree(cs->hw.ser); | 430 | kfree(cs->hw.ser); |
419 | cs->hw.ser = NULL; | 431 | cs->hw.ser = NULL; |
@@ -422,7 +434,7 @@ static int gigaset_initcshw(struct cardstate *cs) | |||
422 | dev_set_drvdata(&cs->hw.ser->dev.dev, cs); | 434 | dev_set_drvdata(&cs->hw.ser->dev.dev, cs); |
423 | 435 | ||
424 | tasklet_init(&cs->write_tasklet, | 436 | tasklet_init(&cs->write_tasklet, |
425 | &gigaset_modem_fill, (unsigned long) cs); | 437 | &gigaset_modem_fill, (unsigned long) cs); |
426 | return 1; | 438 | return 1; |
427 | } | 439 | } |
428 | 440 | ||
@@ -434,7 +446,8 @@ static int gigaset_initcshw(struct cardstate *cs) | |||
434 | * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c | 446 | * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c |
435 | * and by "if_lock" and "if_termios" in interface.c | 447 | * and by "if_lock" and "if_termios" in interface.c |
436 | */ | 448 | */ |
437 | static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state) | 449 | static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, |
450 | unsigned new_state) | ||
438 | { | 451 | { |
439 | struct tty_struct *tty = cs->hw.ser->tty; | 452 | struct tty_struct *tty = cs->hw.ser->tty; |
440 | unsigned int set, clear; | 453 | unsigned int set, clear; |
@@ -520,8 +533,8 @@ gigaset_tty_open(struct tty_struct *tty) | |||
520 | } | 533 | } |
521 | 534 | ||
522 | /* allocate memory for our device state and intialize it */ | 535 | /* allocate memory for our device state and intialize it */ |
523 | if (!(cs = gigaset_initcs(driver, 1, 1, 0, cidmode, | 536 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); |
524 | GIGASET_MODULENAME))) | 537 | if (!cs) |
525 | goto error; | 538 | goto error; |
526 | 539 | ||
527 | cs->dev = &cs->hw.ser->dev.dev; | 540 | cs->dev = &cs->hw.ser->dev.dev; |
@@ -690,7 +703,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, | |||
690 | 703 | ||
691 | if (!cs) | 704 | if (!cs) |
692 | return; | 705 | return; |
693 | if (!(inbuf = cs->inbuf)) { | 706 | inbuf = cs->inbuf; |
707 | if (!inbuf) { | ||
694 | dev_err(cs->dev, "%s: no inbuf\n", __func__); | 708 | dev_err(cs->dev, "%s: no inbuf\n", __func__); |
695 | cs_put(cs); | 709 | cs_put(cs); |
696 | return; | 710 | return; |
@@ -770,18 +784,21 @@ static int __init ser_gigaset_init(void) | |||
770 | int rc; | 784 | int rc; |
771 | 785 | ||
772 | gig_dbg(DEBUG_INIT, "%s", __func__); | 786 | gig_dbg(DEBUG_INIT, "%s", __func__); |
773 | if ((rc = platform_driver_register(&device_driver)) != 0) { | 787 | rc = platform_driver_register(&device_driver); |
788 | if (rc != 0) { | ||
774 | pr_err("error %d registering platform driver\n", rc); | 789 | pr_err("error %d registering platform driver\n", rc); |
775 | return rc; | 790 | return rc; |
776 | } | 791 | } |
777 | 792 | ||
778 | /* allocate memory for our driver state and intialize it */ | 793 | /* allocate memory for our driver state and intialize it */ |
779 | if (!(driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 794 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
780 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 795 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
781 | &ops, THIS_MODULE))) | 796 | &ops, THIS_MODULE); |
797 | if (!driver) | ||
782 | goto error; | 798 | goto error; |
783 | 799 | ||
784 | if ((rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc)) != 0) { | 800 | rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc); |
801 | if (rc != 0) { | ||
785 | pr_err("error %d registering line discipline\n", rc); | 802 | pr_err("error %d registering line discipline\n", rc); |
786 | goto error; | 803 | goto error; |
787 | } | 804 | } |
@@ -808,7 +825,8 @@ static void __exit ser_gigaset_exit(void) | |||
808 | driver = NULL; | 825 | driver = NULL; |
809 | } | 826 | } |
810 | 827 | ||
811 | if ((rc = tty_unregister_ldisc(N_GIGASET_M101)) != 0) | 828 | rc = tty_unregister_ldisc(N_GIGASET_M101); |
829 | if (rc != 0) | ||
812 | pr_err("error %d unregistering line discipline\n", rc); | 830 | pr_err("error %d unregistering line discipline\n", rc); |
813 | 831 | ||
814 | platform_driver_unregister(&device_driver); | 832 | platform_driver_unregister(&device_driver); |
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 4deb1ab0dbf8..f56b2a83793e 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c | |||
@@ -43,14 +43,14 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); | |||
43 | #define GIGASET_MODULENAME "usb_gigaset" | 43 | #define GIGASET_MODULENAME "usb_gigaset" |
44 | #define GIGASET_DEVNAME "ttyGU" | 44 | #define GIGASET_DEVNAME "ttyGU" |
45 | 45 | ||
46 | #define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256 | 46 | #define IF_WRITEBUF 2000 /* arbitrary limit */ |
47 | 47 | ||
48 | /* Values for the Gigaset M105 Data */ | 48 | /* Values for the Gigaset M105 Data */ |
49 | #define USB_M105_VENDOR_ID 0x0681 | 49 | #define USB_M105_VENDOR_ID 0x0681 |
50 | #define USB_M105_PRODUCT_ID 0x0009 | 50 | #define USB_M105_PRODUCT_ID 0x0009 |
51 | 51 | ||
52 | /* table of devices that work with this driver */ | 52 | /* table of devices that work with this driver */ |
53 | static const struct usb_device_id gigaset_table [] = { | 53 | static const struct usb_device_id gigaset_table[] = { |
54 | { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, | 54 | { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, |
55 | { } /* Terminating entry */ | 55 | { } /* Terminating entry */ |
56 | }; | 56 | }; |
@@ -97,8 +97,8 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); | |||
97 | * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 | 97 | * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 |
98 | * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). | 98 | * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). |
99 | * xx is usually 0x00 but was 0x7e before starting data transfer | 99 | * xx is usually 0x00 but was 0x7e before starting data transfer |
100 | * in unimodem mode. So, this might be an array of characters that need | 100 | * in unimodem mode. So, this might be an array of characters that |
101 | * special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. | 101 | * need special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. |
102 | * | 102 | * |
103 | * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two | 103 | * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two |
104 | * flags per packet. | 104 | * flags per packet. |
@@ -114,7 +114,7 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); | |||
114 | static int gigaset_resume(struct usb_interface *intf); | 114 | static int gigaset_resume(struct usb_interface *intf); |
115 | static int gigaset_pre_reset(struct usb_interface *intf); | 115 | static int gigaset_pre_reset(struct usb_interface *intf); |
116 | 116 | ||
117 | static struct gigaset_driver *driver = NULL; | 117 | static struct gigaset_driver *driver; |
118 | 118 | ||
119 | /* usb specific object needed to register this driver with the usb subsystem */ | 119 | /* usb specific object needed to register this driver with the usb subsystem */ |
120 | static struct usb_driver gigaset_usb_driver = { | 120 | static struct usb_driver gigaset_usb_driver = { |
@@ -141,6 +141,7 @@ struct usb_cardstate { | |||
141 | struct urb *bulk_out_urb; | 141 | struct urb *bulk_out_urb; |
142 | 142 | ||
143 | /* Input buffer */ | 143 | /* Input buffer */ |
144 | unsigned char *rcvbuf; | ||
144 | int rcvbuf_size; | 145 | int rcvbuf_size; |
145 | struct urb *read_urb; | 146 | struct urb *read_urb; |
146 | __u8 int_in_endpointAddr; | 147 | __u8 int_in_endpointAddr; |
@@ -164,13 +165,11 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, | |||
164 | val = tiocm_to_gigaset(new_state); | 165 | val = tiocm_to_gigaset(new_state); |
165 | 166 | ||
166 | gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); | 167 | gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); |
167 | // don't use this in an interrupt/BH | ||
168 | r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, | 168 | r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, |
169 | (val & 0xff) | ((mask & 0xff) << 8), 0, | 169 | (val & 0xff) | ((mask & 0xff) << 8), 0, |
170 | NULL, 0, 2000 /* timeout? */); | 170 | NULL, 0, 2000 /* timeout? */); |
171 | if (r < 0) | 171 | if (r < 0) |
172 | return r; | 172 | return r; |
173 | //.. | ||
174 | return 0; | 173 | return 0; |
175 | } | 174 | } |
176 | 175 | ||
@@ -220,7 +219,6 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) | |||
220 | cflag &= CBAUD; | 219 | cflag &= CBAUD; |
221 | 220 | ||
222 | switch (cflag) { | 221 | switch (cflag) { |
223 | //FIXME more values? | ||
224 | case B300: rate = 300; break; | 222 | case B300: rate = 300; break; |
225 | case B600: rate = 600; break; | 223 | case B600: rate = 600; break; |
226 | case B1200: rate = 1200; break; | 224 | case B1200: rate = 1200; break; |
@@ -273,7 +271,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) | |||
273 | /* set the number of stop bits */ | 271 | /* set the number of stop bits */ |
274 | if (cflag & CSTOPB) { | 272 | if (cflag & CSTOPB) { |
275 | if ((cflag & CSIZE) == CS5) | 273 | if ((cflag & CSIZE) == CS5) |
276 | val |= 1; /* 1.5 stop bits */ //FIXME is this okay? | 274 | val |= 1; /* 1.5 stop bits */ |
277 | else | 275 | else |
278 | val |= 2; /* 2 stop bits */ | 276 | val |= 2; /* 2 stop bits */ |
279 | } | 277 | } |
@@ -282,7 +280,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) | |||
282 | } | 280 | } |
283 | 281 | ||
284 | 282 | ||
285 | /*================================================================================================================*/ | 283 | /*============================================================================*/ |
286 | static int gigaset_init_bchannel(struct bc_state *bcs) | 284 | static int gigaset_init_bchannel(struct bc_state *bcs) |
287 | { | 285 | { |
288 | /* nothing to do for M10x */ | 286 | /* nothing to do for M10x */ |
@@ -344,7 +342,6 @@ static void gigaset_modem_fill(unsigned long data) | |||
344 | if (write_modem(cs) < 0) { | 342 | if (write_modem(cs) < 0) { |
345 | gig_dbg(DEBUG_OUTPUT, | 343 | gig_dbg(DEBUG_OUTPUT, |
346 | "modem_fill: write_modem failed"); | 344 | "modem_fill: write_modem failed"); |
347 | // FIXME should we tell the LL? | ||
348 | again = 1; /* no callback will be called! */ | 345 | again = 1; /* no callback will be called! */ |
349 | } | 346 | } |
350 | } | 347 | } |
@@ -356,8 +353,8 @@ static void gigaset_modem_fill(unsigned long data) | |||
356 | */ | 353 | */ |
357 | static void gigaset_read_int_callback(struct urb *urb) | 354 | static void gigaset_read_int_callback(struct urb *urb) |
358 | { | 355 | { |
359 | struct inbuf_t *inbuf = urb->context; | 356 | struct cardstate *cs = urb->context; |
360 | struct cardstate *cs = inbuf->cs; | 357 | struct inbuf_t *inbuf = cs->inbuf; |
361 | int status = urb->status; | 358 | int status = urb->status; |
362 | int r; | 359 | int r; |
363 | unsigned numbytes; | 360 | unsigned numbytes; |
@@ -368,7 +365,7 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
368 | numbytes = urb->actual_length; | 365 | numbytes = urb->actual_length; |
369 | 366 | ||
370 | if (numbytes) { | 367 | if (numbytes) { |
371 | src = inbuf->rcvbuf; | 368 | src = cs->hw.usb->rcvbuf; |
372 | if (unlikely(*src)) | 369 | if (unlikely(*src)) |
373 | dev_warn(cs->dev, | 370 | dev_warn(cs->dev, |
374 | "%s: There was no leading 0, but 0x%02x!\n", | 371 | "%s: There was no leading 0, but 0x%02x!\n", |
@@ -440,7 +437,7 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) | |||
440 | struct cmdbuf_t *tcb; | 437 | struct cmdbuf_t *tcb; |
441 | unsigned long flags; | 438 | unsigned long flags; |
442 | int count; | 439 | int count; |
443 | int status = -ENOENT; // FIXME | 440 | int status = -ENOENT; |
444 | struct usb_cardstate *ucs = cs->hw.usb; | 441 | struct usb_cardstate *ucs = cs->hw.usb; |
445 | 442 | ||
446 | do { | 443 | do { |
@@ -480,7 +477,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) | |||
480 | ucs->busy = 1; | 477 | ucs->busy = 1; |
481 | 478 | ||
482 | spin_lock_irqsave(&cs->lock, flags); | 479 | spin_lock_irqsave(&cs->lock, flags); |
483 | status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; | 480 | status = cs->connected ? |
481 | usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : | ||
482 | -ENODEV; | ||
484 | spin_unlock_irqrestore(&cs->lock, flags); | 483 | spin_unlock_irqrestore(&cs->lock, flags); |
485 | 484 | ||
486 | if (status) { | 485 | if (status) { |
@@ -510,8 +509,8 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | |||
510 | 509 | ||
511 | if (len <= 0) | 510 | if (len <= 0) |
512 | return 0; | 511 | return 0; |
513 | 512 | cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); | |
514 | if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { | 513 | if (!cb) { |
515 | dev_err(cs->dev, "%s: out of memory\n", __func__); | 514 | dev_err(cs->dev, "%s: out of memory\n", __func__); |
516 | return -ENOMEM; | 515 | return -ENOMEM; |
517 | } | 516 | } |
@@ -637,9 +636,7 @@ static int write_modem(struct cardstate *cs) | |||
637 | return -EINVAL; | 636 | return -EINVAL; |
638 | } | 637 | } |
639 | 638 | ||
640 | /* Copy data to bulk out buffer and // FIXME copying not necessary | 639 | /* Copy data to bulk out buffer and transmit data */ |
641 | * transmit data | ||
642 | */ | ||
643 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); | 640 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); |
644 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); | 641 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); |
645 | skb_pull(bcs->tx_skb, count); | 642 | skb_pull(bcs->tx_skb, count); |
@@ -650,7 +647,8 @@ static int write_modem(struct cardstate *cs) | |||
650 | if (cs->connected) { | 647 | if (cs->connected) { |
651 | usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, | 648 | usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, |
652 | usb_sndbulkpipe(ucs->udev, | 649 | usb_sndbulkpipe(ucs->udev, |
653 | ucs->bulk_out_endpointAddr & 0x0f), | 650 | ucs->bulk_out_endpointAddr & |
651 | 0x0f), | ||
654 | ucs->bulk_out_buffer, count, | 652 | ucs->bulk_out_buffer, count, |
655 | gigaset_write_bulk_callback, cs); | 653 | gigaset_write_bulk_callback, cs); |
656 | ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); | 654 | ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); |
@@ -666,7 +664,7 @@ static int write_modem(struct cardstate *cs) | |||
666 | 664 | ||
667 | if (!bcs->tx_skb->len) { | 665 | if (!bcs->tx_skb->len) { |
668 | /* skb sent completely */ | 666 | /* skb sent completely */ |
669 | gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? | 667 | gigaset_skb_sent(bcs, bcs->tx_skb); |
670 | 668 | ||
671 | gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", | 669 | gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", |
672 | (unsigned long) bcs->tx_skb); | 670 | (unsigned long) bcs->tx_skb); |
@@ -763,8 +761,8 @@ static int gigaset_probe(struct usb_interface *interface, | |||
763 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 761 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
764 | ucs->rcvbuf_size = buffer_size; | 762 | ucs->rcvbuf_size = buffer_size; |
765 | ucs->int_in_endpointAddr = endpoint->bEndpointAddress; | 763 | ucs->int_in_endpointAddr = endpoint->bEndpointAddress; |
766 | cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL); | 764 | ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL); |
767 | if (!cs->inbuf[0].rcvbuf) { | 765 | if (!ucs->rcvbuf) { |
768 | dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); | 766 | dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); |
769 | retval = -ENOMEM; | 767 | retval = -ENOMEM; |
770 | goto error; | 768 | goto error; |
@@ -773,9 +771,9 @@ static int gigaset_probe(struct usb_interface *interface, | |||
773 | usb_fill_int_urb(ucs->read_urb, udev, | 771 | usb_fill_int_urb(ucs->read_urb, udev, |
774 | usb_rcvintpipe(udev, | 772 | usb_rcvintpipe(udev, |
775 | endpoint->bEndpointAddress & 0x0f), | 773 | endpoint->bEndpointAddress & 0x0f), |
776 | cs->inbuf[0].rcvbuf, buffer_size, | 774 | ucs->rcvbuf, buffer_size, |
777 | gigaset_read_int_callback, | 775 | gigaset_read_int_callback, |
778 | cs->inbuf + 0, endpoint->bInterval); | 776 | cs, endpoint->bInterval); |
779 | 777 | ||
780 | retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); | 778 | retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); |
781 | if (retval) { | 779 | if (retval) { |
@@ -789,7 +787,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
789 | 787 | ||
790 | if (!gigaset_start(cs)) { | 788 | if (!gigaset_start(cs)) { |
791 | tasklet_kill(&cs->write_tasklet); | 789 | tasklet_kill(&cs->write_tasklet); |
792 | retval = -ENODEV; //FIXME | 790 | retval = -ENODEV; |
793 | goto error; | 791 | goto error; |
794 | } | 792 | } |
795 | return 0; | 793 | return 0; |
@@ -798,11 +796,11 @@ error: | |||
798 | usb_kill_urb(ucs->read_urb); | 796 | usb_kill_urb(ucs->read_urb); |
799 | kfree(ucs->bulk_out_buffer); | 797 | kfree(ucs->bulk_out_buffer); |
800 | usb_free_urb(ucs->bulk_out_urb); | 798 | usb_free_urb(ucs->bulk_out_urb); |
801 | kfree(cs->inbuf[0].rcvbuf); | 799 | kfree(ucs->rcvbuf); |
802 | usb_free_urb(ucs->read_urb); | 800 | usb_free_urb(ucs->read_urb); |
803 | usb_set_intfdata(interface, NULL); | 801 | usb_set_intfdata(interface, NULL); |
804 | ucs->read_urb = ucs->bulk_out_urb = NULL; | 802 | ucs->read_urb = ucs->bulk_out_urb = NULL; |
805 | cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; | 803 | ucs->rcvbuf = ucs->bulk_out_buffer = NULL; |
806 | usb_put_dev(ucs->udev); | 804 | usb_put_dev(ucs->udev); |
807 | ucs->udev = NULL; | 805 | ucs->udev = NULL; |
808 | ucs->interface = NULL; | 806 | ucs->interface = NULL; |
@@ -831,10 +829,10 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
831 | 829 | ||
832 | kfree(ucs->bulk_out_buffer); | 830 | kfree(ucs->bulk_out_buffer); |
833 | usb_free_urb(ucs->bulk_out_urb); | 831 | usb_free_urb(ucs->bulk_out_urb); |
834 | kfree(cs->inbuf[0].rcvbuf); | 832 | kfree(ucs->rcvbuf); |
835 | usb_free_urb(ucs->read_urb); | 833 | usb_free_urb(ucs->read_urb); |
836 | ucs->read_urb = ucs->bulk_out_urb = NULL; | 834 | ucs->read_urb = ucs->bulk_out_urb = NULL; |
837 | cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; | 835 | ucs->rcvbuf = ucs->bulk_out_buffer = NULL; |
838 | 836 | ||
839 | usb_put_dev(ucs->udev); | 837 | usb_put_dev(ucs->udev); |
840 | ucs->interface = NULL; | 838 | ucs->interface = NULL; |
@@ -916,9 +914,10 @@ static int __init usb_gigaset_init(void) | |||
916 | int result; | 914 | int result; |
917 | 915 | ||
918 | /* allocate memory for our driver state and intialize it */ | 916 | /* allocate memory for our driver state and intialize it */ |
919 | if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 917 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
920 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 918 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
921 | &ops, THIS_MODULE)) == NULL) | 919 | &ops, THIS_MODULE); |
920 | if (driver == NULL) | ||
922 | goto error; | 921 | goto error; |
923 | 922 | ||
924 | /* register this driver with the USB subsystem */ | 923 | /* register this driver with the USB subsystem */ |
diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c index ff3a4e290da3..7726afdbb40b 100644 --- a/drivers/isdn/hardware/mISDN/speedfax.c +++ b/drivers/isdn/hardware/mISDN/speedfax.c | |||
@@ -110,6 +110,7 @@ set_debug(const char *val, struct kernel_param *kp) | |||
110 | MODULE_AUTHOR("Karsten Keil"); | 110 | MODULE_AUTHOR("Karsten Keil"); |
111 | MODULE_LICENSE("GPL v2"); | 111 | MODULE_LICENSE("GPL v2"); |
112 | MODULE_VERSION(SPEEDFAX_REV); | 112 | MODULE_VERSION(SPEEDFAX_REV); |
113 | MODULE_FIRMWARE("isdn/ISAR.BIN"); | ||
113 | module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); | 114 | module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); |
114 | MODULE_PARM_DESC(debug, "Speedfax debug mask"); | 115 | MODULE_PARM_DESC(debug, "Speedfax debug mask"); |
115 | module_param(irqloops, uint, S_IRUGO | S_IWUSR); | 116 | module_param(irqloops, uint, S_IRUGO | S_IWUSR); |
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index feb0fa45b664..fcfe17a19a61 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c | |||
@@ -779,7 +779,7 @@ base_sock_create(struct net *net, struct socket *sock, int protocol) | |||
779 | } | 779 | } |
780 | 780 | ||
781 | static int | 781 | static int |
782 | mISDN_sock_create(struct net *net, struct socket *sock, int proto) | 782 | mISDN_sock_create(struct net *net, struct socket *sock, int proto, int kern) |
783 | { | 783 | { |
784 | int err = -EPROTONOSUPPORT; | 784 | int err = -EPROTONOSUPPORT; |
785 | 785 | ||
@@ -808,8 +808,7 @@ mISDN_sock_create(struct net *net, struct socket *sock, int proto) | |||
808 | return err; | 808 | return err; |
809 | } | 809 | } |
810 | 810 | ||
811 | static struct | 811 | static const struct net_proto_family mISDN_sock_family_ops = { |
812 | net_proto_family mISDN_sock_family_ops = { | ||
813 | .owner = THIS_MODULE, | 812 | .owner = THIS_MODULE, |
814 | .family = PF_ISDN, | 813 | .family = PF_ISDN, |
815 | .create = mISDN_sock_create, | 814 | .create = mISDN_sock_create, |