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