• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 1999-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains functions to send TS 07.10 frames
22  *
23  ******************************************************************************/
24 #include "bt_target.h"
25 #include "gki.h"
26 #include "rfcdefs.h"
27 #include "port_api.h"
28 #include "l2c_api.h"
29 #include "port_int.h"
30 #include "rfc_int.h"
31 
32 /*******************************************************************************
33 **
34 ** Function         rfc_send_sabme
35 **
36 ** Description      This function sends SABME frame.
37 **
38 *******************************************************************************/
rfc_send_sabme(tRFC_MCB * p_mcb,UINT8 dlci)39 void rfc_send_sabme (tRFC_MCB *p_mcb, UINT8 dlci)
40 {
41     BT_HDR  *p_buf;
42     UINT8   *p_data;
43     UINT8   cr = RFCOMM_CR(p_mcb->is_initiator, TRUE);
44 
45     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
46         return;
47 
48     p_buf->offset = L2CAP_MIN_OFFSET;
49     p_data = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
50 
51     /* SABME frame, command, PF = 1, dlci */
52     *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
53     *p_data++ = RFCOMM_SABME | RFCOMM_PF;
54     *p_data++ = RFCOMM_EA | 0;
55 
56     *p_data   = RFCOMM_SABME_FCS ((UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET, cr, dlci);
57 
58     p_buf->len = 4;
59 
60     rfc_check_send_cmd(p_mcb, p_buf);
61 }
62 
63 
64 /*******************************************************************************
65 **
66 ** Function         rfc_send_ua
67 **
68 ** Description      This function sends UA frame.
69 **
70 *******************************************************************************/
rfc_send_ua(tRFC_MCB * p_mcb,UINT8 dlci)71 void rfc_send_ua (tRFC_MCB *p_mcb, UINT8 dlci)
72 {
73     BT_HDR  *p_buf;
74     UINT8   *p_data;
75     UINT8   cr = RFCOMM_CR(p_mcb->is_initiator, FALSE);
76 
77     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
78         return;
79 
80     p_buf->offset = L2CAP_MIN_OFFSET;
81     p_data = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
82 
83     /* ua frame, response, PF = 1, dlci */
84     *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
85     *p_data++ = RFCOMM_UA | RFCOMM_PF;
86     *p_data++ = RFCOMM_EA | 0;
87 
88     *p_data   = RFCOMM_UA_FCS ((UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET, cr, dlci);
89 
90     p_buf->len = 4;
91 
92     rfc_check_send_cmd(p_mcb, p_buf);
93 }
94 
95 
96 /*******************************************************************************
97 **
98 ** Function         rfc_send_dm
99 **
100 ** Description      This function sends DM frame.
101 **
102 *******************************************************************************/
rfc_send_dm(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN pf)103 void rfc_send_dm (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN pf)
104 {
105     BT_HDR  *p_buf;
106     UINT8   *p_data;
107     UINT8   cr = RFCOMM_CR(p_mcb->is_initiator, FALSE);
108 
109     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
110         return;
111 
112     p_buf->offset = L2CAP_MIN_OFFSET;
113     p_data = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
114 
115     /* DM frame, response, PF = 1, dlci */
116     *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
117     *p_data++ = RFCOMM_DM | ((pf) ? RFCOMM_PF : 0);
118     *p_data++ = RFCOMM_EA | 0;
119 
120     *p_data   = RFCOMM_DM_FCS ((UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET, cr, dlci);
121 
122     p_buf->len = 4;
123 
124     rfc_check_send_cmd(p_mcb, p_buf);
125 }
126 
127 
128 /*******************************************************************************
129 **
130 ** Function         rfc_send_disc
131 **
132 ** Description      This function sends DISC frame.
133 **
134 *******************************************************************************/
rfc_send_disc(tRFC_MCB * p_mcb,UINT8 dlci)135 void rfc_send_disc (tRFC_MCB *p_mcb, UINT8 dlci)
136 {
137     BT_HDR  *p_buf;
138     UINT8   *p_data;
139     UINT8   cr = RFCOMM_CR(p_mcb->is_initiator, TRUE);
140 
141     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
142         return;
143 
144     p_buf->offset = L2CAP_MIN_OFFSET;
145     p_data = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
146 
147     /* DISC frame, command, PF = 1, dlci */
148     *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
149     *p_data++ = RFCOMM_DISC | RFCOMM_PF;
150     *p_data++ = RFCOMM_EA | 0;
151 
152     *p_data   = RFCOMM_DISC_FCS ((UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET, cr, dlci);
153 
154     p_buf->len = 4;
155 
156     rfc_check_send_cmd(p_mcb, p_buf);
157 }
158 
159 
160 /*******************************************************************************
161 **
162 ** Function         rfc_send_buf_uih
163 **
164 ** Description      This function sends UIH frame.
165 **
166 *******************************************************************************/
rfc_send_buf_uih(tRFC_MCB * p_mcb,UINT8 dlci,BT_HDR * p_buf)167 void rfc_send_buf_uih (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf)
168 {
169     UINT8   *p_data;
170     UINT8   cr = RFCOMM_CR(p_mcb->is_initiator, TRUE);
171     UINT8   credits;
172 
173     p_buf->offset -= RFCOMM_CTRL_FRAME_LEN;
174     if (p_buf->len > 127)
175         p_buf->offset--;
176 
177     if (dlci)
178         credits = (UINT8)p_buf->layer_specific;
179     else
180         credits = 0;
181 
182     if (credits)
183         p_buf->offset--;
184 
185     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
186 
187     /* UIH frame, command, PF = 0, dlci */
188     *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
189     *p_data++ = RFCOMM_UIH | ((credits) ? RFCOMM_PF : 0);
190     if (p_buf->len <= 127)
191     {
192         *p_data++   = RFCOMM_EA | (p_buf->len << 1);
193         p_buf->len += 3;
194     }
195     else
196     {
197         *p_data++   = (p_buf->len & 0x7f) << 1;
198         *p_data++   = p_buf->len >> RFCOMM_SHIFT_LENGTH2;
199         p_buf->len += 4;
200     }
201 
202     if (credits)
203     {
204         *p_data++ = credits;
205         p_buf->len++;
206     }
207 
208     p_data  = (UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len++;
209 
210     *p_data = RFCOMM_UIH_FCS ((UINT8 *)(p_buf + 1) + p_buf->offset, dlci);
211 
212     if (dlci == RFCOMM_MX_DLCI)
213     {
214         rfc_check_send_cmd(p_mcb, p_buf);
215     }
216     else
217     {
218 
219         L2CA_DataWrite (p_mcb->lcid, p_buf);
220     }
221 }
222 
223 
224 /*******************************************************************************
225 **
226 ** Function         rfc_send_pn
227 **
228 ** Description      This function sends DLC Parameters Negotiation Frame.
229 **
230 *******************************************************************************/
rfc_send_pn(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN is_command,UINT16 mtu,UINT8 cl,UINT8 k)231 void rfc_send_pn (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN is_command, UINT16 mtu, UINT8 cl, UINT8 k)
232 {
233     BT_HDR   *p_buf;
234     UINT8    *p_data;
235 
236     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
237         return;
238 
239     p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
240     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
241 
242     *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_PN;
243     *p_data++ = RFCOMM_EA | (RFCOMM_MX_PN_LEN << 1);
244 
245     *p_data++ = dlci;
246     *p_data++ = RFCOMM_PN_FRAM_TYPE_UIH | cl;
247 
248     /* It appeared that we need to reply with the same priority bits as we received.
249     ** We will use the fact that we reply in the same context so rx_frame can still be used.
250     */
251     if (is_command)
252         *p_data++ = RFCOMM_PN_PRIORITY_0;
253     else
254         *p_data++ = rfc_cb.rfc.rx_frame.u.pn.priority;
255 
256     *p_data++ = RFCOMM_T1_DSEC;
257     *p_data++ = mtu & 0xFF;
258     *p_data++ = mtu >> 8;
259     *p_data++ = RFCOMM_N2;
260     *p_data   = k;
261 
262     /* Total length is sizeof PN data + mx header 2 */
263     p_buf->len = RFCOMM_MX_PN_LEN + 2;
264 
265     rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
266 }
267 
268 
269 /*******************************************************************************
270 **
271 ** Function         rfc_send_fcon
272 **
273 ** Description      This function sends Flow Control On Command.
274 **
275 *******************************************************************************/
rfc_send_fcon(tRFC_MCB * p_mcb,BOOLEAN is_command)276 void rfc_send_fcon (tRFC_MCB *p_mcb, BOOLEAN is_command)
277 {
278     BT_HDR  *p_buf;
279     UINT8   *p_data;
280 
281     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
282         return;
283 
284     p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
285     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
286 
287     *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_FCON;
288     *p_data++ = RFCOMM_EA | (RFCOMM_MX_FCON_LEN << 1);
289 
290     /* Total length is sizeof FCON data + mx header 2 */
291     p_buf->len = RFCOMM_MX_FCON_LEN + 2;
292 
293     rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
294 }
295 
296 
297 /*******************************************************************************
298 **
299 ** Function         rfc_send_fcoff
300 **
301 ** Description      This function sends Flow Control Off Command.
302 **
303 *******************************************************************************/
rfc_send_fcoff(tRFC_MCB * p_mcb,BOOLEAN is_command)304 void rfc_send_fcoff (tRFC_MCB *p_mcb, BOOLEAN is_command)
305 {
306     BT_HDR  *p_buf;
307     UINT8   *p_data;
308 
309     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
310         return;
311 
312     p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
313     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
314 
315     *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_FCOFF;
316     *p_data++ = RFCOMM_EA | (RFCOMM_MX_FCOFF_LEN << 1);
317 
318     /* Total length is sizeof FCOFF data + mx header 2 */
319     p_buf->len = RFCOMM_MX_FCOFF_LEN + 2;
320 
321     rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
322 }
323 
324 
325 /*******************************************************************************
326 **
327 ** Function         rfc_send_msc
328 **
329 ** Description      This function sends Modem Status Command Frame.
330 **
331 *******************************************************************************/
rfc_send_msc(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN is_command,tPORT_CTRL * p_pars)332 void rfc_send_msc (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN is_command,
333                    tPORT_CTRL *p_pars)
334 {
335     BT_HDR  *p_buf;
336     UINT8   *p_data;
337     UINT8   signals;
338     UINT8   break_duration;
339     UINT8   len;
340 
341     signals        = p_pars->modem_signal;
342     break_duration = p_pars->break_signal;
343 
344     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
345         return;
346 
347     p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
348     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
349 
350     if (break_duration)
351         len = RFCOMM_MX_MSC_LEN_WITH_BREAK;
352     else
353         len = RFCOMM_MX_MSC_LEN_NO_BREAK;
354 
355     *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_MSC;
356     *p_data++ = RFCOMM_EA | (len << 1);
357 
358     *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI);
359     *p_data++ = RFCOMM_EA |
360                 ((p_pars->fc)                    ? RFCOMM_MSC_FC : 0)  |
361                 ((signals & MODEM_SIGNAL_DTRDSR) ? RFCOMM_MSC_RTC : 0) |
362                 ((signals & MODEM_SIGNAL_RTSCTS) ? RFCOMM_MSC_RTR : 0) |
363                 ((signals & MODEM_SIGNAL_RI)     ? RFCOMM_MSC_IC : 0)  |
364                 ((signals & MODEM_SIGNAL_DCD)    ? RFCOMM_MSC_DV : 0);
365 
366     if (break_duration)
367     {
368         *p_data++ = RFCOMM_EA | RFCOMM_MSC_BREAK_PRESENT_MASK |
369                     (break_duration << RFCOMM_MSC_SHIFT_BREAK);
370     }
371 
372     /* Total length is sizeof MSC data + mx header 2 */
373     p_buf->len = len + 2;
374 
375     rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
376 }
377 
378 
379 /*******************************************************************************
380 **
381 ** Function         rfc_send_rls
382 **
383 ** Description      This function sends Remote Line Status Command Frame.
384 **
385 *******************************************************************************/
rfc_send_rls(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN is_command,UINT8 status)386 void rfc_send_rls (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN is_command, UINT8 status)
387 {
388     BT_HDR  *p_buf;
389     UINT8   *p_data;
390 
391     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
392         return;
393 
394     p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
395     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
396 
397     *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_RLS;
398     *p_data++ = RFCOMM_EA | (RFCOMM_MX_RLS_LEN << 1);
399 
400     *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI);
401     *p_data++ = RFCOMM_RLS_ERROR | status;
402 
403     /* Total length is sizeof RLS data + mx header 2 */
404     p_buf->len = RFCOMM_MX_RLS_LEN + 2;
405 
406     rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
407 }
408 
409 
410 /*******************************************************************************
411 **
412 ** Function         rfc_send_nsc
413 **
414 ** Description      This function sends Non Supported Command Response.
415 **
416 *******************************************************************************/
rfc_send_nsc(tRFC_MCB * p_mcb)417 void rfc_send_nsc (tRFC_MCB *p_mcb)
418 {
419     BT_HDR  *p_buf;
420     UINT8   *p_data;
421 
422     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
423         return;
424 
425     p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
426     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
427 
428     *p_data++ = RFCOMM_EA | RFCOMM_I_CR(FALSE) | RFCOMM_MX_NSC;
429     *p_data++ = RFCOMM_EA | (RFCOMM_MX_NSC_LEN << 1);
430 
431     *p_data++ =  rfc_cb.rfc.rx_frame.ea |
432                 (rfc_cb.rfc.rx_frame.cr << RFCOMM_SHIFT_CR) |
433                  rfc_cb.rfc.rx_frame.type;
434 
435     /* Total length is sizeof NSC data + mx header 2 */
436     p_buf->len = RFCOMM_MX_NSC_LEN + 2;
437 
438     rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
439 }
440 
441 
442 /*******************************************************************************
443 **
444 ** Function         rfc_send_rpn
445 **
446 ** Description      This function sends Remote Port Negotiation Command
447 **
448 *******************************************************************************/
rfc_send_rpn(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN is_command,tPORT_STATE * p_pars,UINT16 mask)449 void rfc_send_rpn (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN is_command,
450                    tPORT_STATE *p_pars, UINT16 mask)
451 {
452     BT_HDR   *p_buf;
453     UINT8    *p_data;
454 
455     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
456         return;
457 
458     p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
459     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
460 
461     *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_RPN;
462 
463     if (!p_pars)
464     {
465         *p_data++ = RFCOMM_EA | (RFCOMM_MX_RPN_REQ_LEN << 1);
466 
467         *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI);
468 
469         p_buf->len = RFCOMM_MX_RPN_REQ_LEN + 2;
470     }
471     else
472     {
473         *p_data++ = RFCOMM_EA | (RFCOMM_MX_RPN_LEN << 1);
474 
475         *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI);
476         *p_data++ = p_pars->baud_rate;
477         *p_data++ =  (p_pars->byte_size << RFCOMM_RPN_BITS_SHIFT)
478                    | (p_pars->stop_bits << RFCOMM_RPN_STOP_BITS_SHIFT)
479                    | (p_pars->parity << RFCOMM_RPN_PARITY_SHIFT)
480                    | (p_pars->parity_type << RFCOMM_RPN_PARITY_TYPE_SHIFT);
481         *p_data++ = p_pars->fc_type;
482         *p_data++ = p_pars->xon_char;
483         *p_data++ = p_pars->xoff_char;
484         *p_data++ = (mask & 0xFF);
485         *p_data++ = (mask >> 8);
486 
487         /* Total length is sizeof RPN data + mx header 2 */
488         p_buf->len = RFCOMM_MX_RPN_LEN + 2;
489     }
490 
491     rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
492 }
493 
494 
495 /*******************************************************************************
496 **
497 ** Function         rfc_send_test
498 **
499 ** Description      This function sends Test frame.
500 **
501 *******************************************************************************/
rfc_send_test(tRFC_MCB * p_mcb,BOOLEAN is_command,BT_HDR * p_buf)502 void rfc_send_test (tRFC_MCB *p_mcb, BOOLEAN is_command, BT_HDR *p_buf)
503 {
504     UINT8    *p_data;
505     UINT16   xx;
506     UINT8    *p_src, *p_dest;
507 
508     /* Shift buffer to give space for header */
509     if (p_buf->offset < (L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2))
510     {
511         p_src  = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len - 1;
512         p_dest = (UINT8 *) (p_buf + 1) + L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2 + p_buf->len - 1;
513 
514         for (xx = 0; xx < p_buf->len; xx++)
515             *p_dest-- = *p_src--;
516 
517         p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2;
518     }
519 
520     /* Adjust offset by number of bytes we are going to fill */
521     p_buf->offset -= 2;
522     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
523 
524     *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_TEST;
525     *p_data++ = RFCOMM_EA | (p_buf->len << 1);
526 
527     p_buf->len += 2;
528 
529     rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
530 }
531 
532 /*******************************************************************************
533 **
534 ** Function         rfc_send_credit
535 **
536 ** Description      This function sends a flow control credit in UIH frame.
537 **
538 *******************************************************************************/
rfc_send_credit(tRFC_MCB * p_mcb,UINT8 dlci,UINT8 credit)539 void rfc_send_credit(tRFC_MCB *p_mcb, UINT8 dlci, UINT8 credit)
540 {
541     BT_HDR   *p_buf;
542     UINT8    *p_data;
543     UINT8    cr = RFCOMM_CR(p_mcb->is_initiator, TRUE);
544 
545     if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
546         return;
547 
548     p_buf->offset = L2CAP_MIN_OFFSET;
549     p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
550 
551     *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
552     *p_data++ = RFCOMM_UIH | RFCOMM_PF;
553     *p_data++ = RFCOMM_EA | 0;
554     *p_data++ = credit;
555     *p_data   = RFCOMM_UIH_FCS ((UINT8 *)(p_buf + 1) + p_buf->offset, dlci);
556 
557     p_buf->len = 5;
558 
559     rfc_check_send_cmd(p_mcb, p_buf);
560 }
561 
562 
563 /*******************************************************************************
564 **
565 ** Function         rfc_parse_data
566 **
567 ** Description      This function processes data packet received from L2CAP
568 **
569 *******************************************************************************/
rfc_parse_data(tRFC_MCB * p_mcb,MX_FRAME * p_frame,BT_HDR * p_buf)570 UINT8 rfc_parse_data (tRFC_MCB *p_mcb, MX_FRAME *p_frame, BT_HDR *p_buf)
571 {
572     UINT8     ead, eal, fcs;
573     UINT8     *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
574     UINT8     *p_start = p_data;
575     UINT16    len;
576 
577     if (p_buf->len < RFCOMM_CTRL_FRAME_LEN)
578     {
579         RFCOMM_TRACE_ERROR1 ("Bad Length1: %d", p_buf->len);
580         return (RFC_EVENT_BAD_FRAME);
581     }
582 
583     RFCOMM_PARSE_CTRL_FIELD (ead, p_frame->cr, p_frame->dlci, p_data);
584     if( !ead )
585     {
586         RFCOMM_TRACE_ERROR0 ("Bad Address(EA must be 1)");
587         return (RFC_EVENT_BAD_FRAME);
588     }
589     RFCOMM_PARSE_TYPE_FIELD (p_frame->type, p_frame->pf, p_data);
590     RFCOMM_PARSE_LEN_FIELD (eal, len, p_data);
591 
592     p_buf->len      -= (3 + !ead + !eal + 1);  /* Additional 1 for FCS */
593     p_buf->offset   += (3 + !ead + !eal);
594 
595     /* handle credit if credit based flow control */
596     if ((p_mcb->flow == PORT_FC_CREDIT) && (p_frame->type == RFCOMM_UIH) &&
597         (p_frame->dlci != RFCOMM_MX_DLCI) && (p_frame->pf == 1))
598     {
599         p_frame->credit = *p_data++;
600         p_buf->len--;
601         p_buf->offset++;
602     }
603     else
604         p_frame->credit = 0;
605 
606     if (p_buf->len != len)
607     {
608         RFCOMM_TRACE_ERROR2 ("Bad Length2 %d %d", p_buf->len, len);
609         return (RFC_EVENT_BAD_FRAME);
610     }
611 
612     fcs = *(p_data + len);
613 
614     /* All control frames that we are sending are sent with P=1, expect */
615     /* reply with F=1 */
616     /* According to TS 07.10 spec ivalid frames are discarded without */
617     /* notification to the sender */
618     switch (p_frame->type)
619     {
620     case RFCOMM_SABME:
621         if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr)
622          || !p_frame->pf || len || !RFCOMM_VALID_DLCI (p_frame->dlci)
623          || !rfc_check_fcs (RFCOMM_CTRL_FRAME_LEN, p_start, fcs))
624         {
625             RFCOMM_TRACE_ERROR0 ("Bad SABME");
626             return (RFC_EVENT_BAD_FRAME);
627         }
628         else
629             return (RFC_EVENT_SABME);
630 
631     case RFCOMM_UA:
632         if (RFCOMM_FRAME_IS_CMD(p_mcb->is_initiator, p_frame->cr)
633           || !p_frame->pf || len || !RFCOMM_VALID_DLCI (p_frame->dlci)
634           || !rfc_check_fcs (RFCOMM_CTRL_FRAME_LEN, p_start, fcs))
635         {
636             RFCOMM_TRACE_ERROR0 ("Bad UA");
637             return (RFC_EVENT_BAD_FRAME);
638         }
639         else
640             return (RFC_EVENT_UA);
641 
642     case RFCOMM_DM:
643         if (RFCOMM_FRAME_IS_CMD(p_mcb->is_initiator, p_frame->cr)
644          || len || !RFCOMM_VALID_DLCI(p_frame->dlci)
645          || !rfc_check_fcs (RFCOMM_CTRL_FRAME_LEN, p_start, fcs))
646         {
647             RFCOMM_TRACE_ERROR0 ("Bad DM");
648             return (RFC_EVENT_BAD_FRAME);
649         }
650         else
651             return (RFC_EVENT_DM);
652 
653     case RFCOMM_DISC:
654         if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr)
655           || !p_frame->pf || len || !RFCOMM_VALID_DLCI(p_frame->dlci)
656           || !rfc_check_fcs (RFCOMM_CTRL_FRAME_LEN, p_start, fcs))
657         {
658             RFCOMM_TRACE_ERROR0 ("Bad DISC");
659             return (RFC_EVENT_BAD_FRAME);
660         }
661         else
662             return (RFC_EVENT_DISC);
663 
664     case RFCOMM_UIH:
665         if (!RFCOMM_VALID_DLCI(p_frame->dlci))
666         {
667             RFCOMM_TRACE_ERROR0 ("Bad UIH - invalid DLCI");
668             return (RFC_EVENT_BAD_FRAME);
669         }
670         else if (!rfc_check_fcs (2, p_start, fcs))
671         {
672             RFCOMM_TRACE_ERROR0 ("Bad UIH - FCS");
673             return (RFC_EVENT_BAD_FRAME);
674         }
675         else if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr))
676         {
677             /* we assume that this is ok to allow bad implementations to work */
678             RFCOMM_TRACE_ERROR0 ("Bad UIH - response");
679             return (RFC_EVENT_UIH);
680         }
681         else
682             return (RFC_EVENT_UIH);
683     }
684 
685     return (RFC_EVENT_BAD_FRAME);
686 }
687 
688 
689 /*******************************************************************************
690 **
691 ** Function         rfc_process_mx_message
692 **
693 ** Description      This function processes UIH frames received on the
694 **                  multiplexer control channel.
695 **
696 *******************************************************************************/
rfc_process_mx_message(tRFC_MCB * p_mcb,BT_HDR * p_buf)697 void rfc_process_mx_message (tRFC_MCB *p_mcb, BT_HDR *p_buf)
698 {
699     UINT8       *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
700     MX_FRAME    *p_rx_frame = &rfc_cb.rfc.rx_frame;
701     UINT16       length  = p_buf->len;
702     UINT8        ea, cr, mx_len;
703     BOOLEAN      is_command;
704 
705     p_rx_frame->ea   = *p_data & RFCOMM_EA;
706     p_rx_frame->cr   = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
707     p_rx_frame->type = *p_data++ & ~(RFCOMM_CR_MASK | RFCOMM_EA_MASK);
708 
709     if (!p_rx_frame->ea || !length)
710     {
711         RFCOMM_TRACE_ERROR2 ("Illegal MX Frame ea:%d len:%d", p_rx_frame->ea, length);
712         GKI_freebuf (p_buf);
713         return;
714     }
715 
716     length--;
717 
718     is_command = p_rx_frame->cr;
719 
720     ea = *p_data & RFCOMM_EA;
721 
722     mx_len = *p_data++ >> RFCOMM_SHIFT_LENGTH1;
723     length--;
724 
725     if (!ea)
726     {
727         mx_len += *p_data++ << RFCOMM_SHIFT_LENGTH2;
728         length --;
729     }
730 
731     if (mx_len != length)
732     {
733         RFCOMM_TRACE_ERROR0 ("Bad MX frame");
734         GKI_freebuf (p_buf);
735         return;
736     }
737 
738     switch (p_rx_frame->type)
739     {
740     case RFCOMM_MX_PN:
741         if (length != RFCOMM_MX_PN_LEN)
742             break;
743 
744         p_rx_frame->dlci            = *p_data++ & RFCOMM_PN_DLCI_MASK;
745         p_rx_frame->u.pn.frame_type = *p_data & RFCOMM_PN_FRAME_TYPE_MASK;
746         p_rx_frame->u.pn.conv_layer = *p_data++ & RFCOMM_PN_CONV_LAYER_MASK;
747         p_rx_frame->u.pn.priority   = *p_data++ & RFCOMM_PN_PRIORITY_MASK;
748         p_rx_frame->u.pn.t1         = *p_data++;
749         p_rx_frame->u.pn.mtu        = *p_data + (*(p_data + 1) << 8);
750         p_data += 2;
751         p_rx_frame->u.pn.n2         = *p_data++;
752         p_rx_frame->u.pn.k          = *p_data++ & RFCOMM_PN_K_MASK;
753 
754         if (!p_rx_frame->dlci
755          || !RFCOMM_VALID_DLCI (p_rx_frame->dlci)
756          || (p_rx_frame->u.pn.mtu < RFCOMM_MIN_MTU)
757          || (p_rx_frame->u.pn.mtu > RFCOMM_MAX_MTU))
758         {
759             RFCOMM_TRACE_ERROR0 ("Bad PN frame");
760             break;
761         }
762 
763         GKI_freebuf (p_buf);
764 
765         rfc_process_pn (p_mcb, is_command, p_rx_frame);
766         return;
767 
768     case RFCOMM_MX_TEST:
769         if (!length)
770             break;
771 
772         p_rx_frame->u.test.p_data   = p_data;
773         p_rx_frame->u.test.data_len = length;
774 
775         p_buf->offset += 2;
776         p_buf->len    -= 2;
777 
778         if (is_command)
779             rfc_send_test (p_mcb, FALSE, p_buf);
780         else
781             rfc_process_test_rsp (p_mcb, p_buf);
782         return;
783 
784     case RFCOMM_MX_FCON:
785         if (length != RFCOMM_MX_FCON_LEN)
786             break;
787 
788         GKI_freebuf (p_buf);
789 
790         rfc_process_fcon (p_mcb, is_command);
791         return;
792 
793     case RFCOMM_MX_FCOFF:
794         if (length != RFCOMM_MX_FCOFF_LEN)
795             break;
796 
797         GKI_freebuf (p_buf);
798 
799         rfc_process_fcoff (p_mcb, is_command);
800         return;
801 
802     case RFCOMM_MX_MSC:
803 
804         ea                   = *p_data & RFCOMM_EA;
805         cr                   = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
806         p_rx_frame->dlci = *p_data++ >> RFCOMM_SHIFT_DLCI;
807 
808         if (!ea || !cr || !p_rx_frame->dlci
809          || !RFCOMM_VALID_DLCI (p_rx_frame->dlci))
810         {
811             RFCOMM_TRACE_ERROR0 ("Bad MSC frame");
812             break;
813         }
814 
815         p_rx_frame->u.msc.signals        = *p_data++;
816 
817         if (mx_len == RFCOMM_MX_MSC_LEN_WITH_BREAK)
818         {
819             p_rx_frame->u.msc.break_present  = *p_data & RFCOMM_MSC_BREAK_PRESENT_MASK;
820             p_rx_frame->u.msc.break_duration = (*p_data & RFCOMM_MSC_BREAK_MASK) >> RFCOMM_MSC_SHIFT_BREAK;
821         }
822         else
823         {
824             p_rx_frame->u.msc.break_present  = FALSE;
825             p_rx_frame->u.msc.break_duration = 0;
826         }
827         GKI_freebuf (p_buf);
828 
829         rfc_process_msc (p_mcb, is_command, p_rx_frame);
830         return;
831 
832     case RFCOMM_MX_NSC:
833         if ((length != RFCOMM_MX_NSC_LEN) || !is_command)
834             break;
835 
836         p_rx_frame->u.nsc.ea   = *p_data & RFCOMM_EA;
837         p_rx_frame->u.nsc.cr   = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
838         p_rx_frame->u.nsc.type = *p_data++ >> RFCOMM_SHIFT_DLCI;
839 
840         GKI_freebuf (p_buf);
841 
842         rfc_process_nsc (p_mcb, p_rx_frame);
843         return;
844 
845     case RFCOMM_MX_RPN:
846         if ((length != RFCOMM_MX_RPN_REQ_LEN) && (length != RFCOMM_MX_RPN_LEN))
847             break;
848 
849         ea                   = *p_data & RFCOMM_EA;
850         cr                   = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
851         p_rx_frame->dlci = *p_data++ >> RFCOMM_SHIFT_DLCI;
852 
853         if (!ea || !cr || !p_rx_frame->dlci
854          || !RFCOMM_VALID_DLCI (p_rx_frame->dlci))
855         {
856             RFCOMM_TRACE_ERROR0 ("Bad RPN frame");
857             break;
858         }
859 
860         p_rx_frame->u.rpn.is_request  = (length == RFCOMM_MX_RPN_REQ_LEN);
861 
862         if (!p_rx_frame->u.rpn.is_request)
863         {
864             p_rx_frame->u.rpn.baud_rate   = *p_data++;
865             p_rx_frame->u.rpn.byte_size   = (*p_data >> RFCOMM_RPN_BITS_SHIFT) & RFCOMM_RPN_BITS_MASK;
866             p_rx_frame->u.rpn.stop_bits   = (*p_data >> RFCOMM_RPN_STOP_BITS_SHIFT) & RFCOMM_RPN_STOP_BITS_MASK;
867             p_rx_frame->u.rpn.parity      = (*p_data >> RFCOMM_RPN_PARITY_SHIFT) & RFCOMM_RPN_PARITY_MASK;
868             p_rx_frame->u.rpn.parity_type = (*p_data++ >> RFCOMM_RPN_PARITY_TYPE_SHIFT) & RFCOMM_RPN_PARITY_TYPE_MASK;
869 
870             p_rx_frame->u.rpn.fc_type     = *p_data++ & RFCOMM_FC_MASK;
871             p_rx_frame->u.rpn.xon_char    = *p_data++;
872             p_rx_frame->u.rpn.xoff_char   = *p_data++;
873             p_rx_frame->u.rpn.param_mask  = (*p_data + (*(p_data + 1) << 8)) & RFCOMM_RPN_PM_MASK;
874         }
875         GKI_freebuf (p_buf);
876 
877         rfc_process_rpn (p_mcb, is_command, p_rx_frame->u.rpn.is_request, p_rx_frame);
878         return;
879 
880     case RFCOMM_MX_RLS:
881         if (length != RFCOMM_MX_RLS_LEN)
882             break;
883 
884         ea = *p_data & RFCOMM_EA;
885         cr = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
886 
887         p_rx_frame->dlci              = *p_data++ >> RFCOMM_SHIFT_DLCI;
888         p_rx_frame->u.rls.line_status = (*p_data & ~0x01);
889 
890         if (!ea || !cr || !p_rx_frame->dlci
891          || !RFCOMM_VALID_DLCI (p_rx_frame->dlci))
892         {
893             RFCOMM_TRACE_ERROR0 ("Bad RPN frame");
894             break;
895         }
896 
897         GKI_freebuf (p_buf);
898 
899         rfc_process_rls (p_mcb, is_command, p_rx_frame);
900         return;
901     }
902 
903     GKI_freebuf (p_buf);
904 
905     if (is_command)
906         rfc_send_nsc (p_mcb);
907 }
908 
909