Changeset View
Standalone View
sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c
Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Send LP_ConnectReq event to the lower layer protocol. Create new connection | * Send LP_ConnectReq event to the lower layer protocol. Create new connection | ||||
* descriptor and initialize it. Create LP_ConnectReq event and send it to the | * descriptor and initialize it. Create LP_ConnectReq event and send it to the | ||||
* lower layer, then adjust connection state and start timer. The function WILL | * lower layer, then adjust connection state and start timer. The function WILL | ||||
* FAIL if connection to the remote unit already exists. | * FAIL if connection to the remote unit already exists. | ||||
*/ | */ | ||||
int | int | ||||
ng_l2cap_lp_con_req(ng_l2cap_p l2cap, bdaddr_p bdaddr) | ng_l2cap_lp_con_req(ng_l2cap_p l2cap, bdaddr_p bdaddr, int type) | ||||
{ | { | ||||
struct ng_mesg *msg = NULL; | struct ng_mesg *msg = NULL; | ||||
ng_hci_lp_con_req_ep *ep = NULL; | ng_hci_lp_con_req_ep *ep = NULL; | ||||
ng_l2cap_con_p con = NULL; | ng_l2cap_con_p con = NULL; | ||||
int error = 0; | int error = 0; | ||||
/* Verify that we DO NOT have connection to the remote unit */ | /* Verify that we DO NOT have connection to the remote unit */ | ||||
con = ng_l2cap_con_by_addr(l2cap, bdaddr); | con = ng_l2cap_con_by_addr(l2cap, bdaddr, type); | ||||
if (con != NULL) { | if (con != NULL) { | ||||
NG_L2CAP_ALERT( | NG_L2CAP_ALERT( | ||||
"%s: %s - unexpected LP_ConnectReq event. " \ | "%s: %s - unexpected LP_ConnectReq event. " \ | ||||
"Connection already exists, state=%d, con_handle=%d\n", | "Connection already exists, state=%d, con_handle=%d\n", | ||||
__func__, NG_NODE_NAME(l2cap->node), con->state, | __func__, NG_NODE_NAME(l2cap->node), con->state, | ||||
con->con_handle); | con->con_handle); | ||||
return (EEXIST); | return (EEXIST); | ||||
} | } | ||||
/* Check if lower layer protocol is still connected */ | /* Check if lower layer protocol is still connected */ | ||||
if (l2cap->hci == NULL || NG_HOOK_NOT_VALID(l2cap->hci)) { | if (l2cap->hci == NULL || NG_HOOK_NOT_VALID(l2cap->hci)) { | ||||
NG_L2CAP_ERR( | NG_L2CAP_ERR( | ||||
"%s: %s - hook \"%s\" is not connected or valid\n", | "%s: %s - hook \"%s\" is not connected or valid\n", | ||||
__func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI); | __func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI); | ||||
return (ENOTCONN); | return (ENOTCONN); | ||||
} | } | ||||
/* Create and intialize new connection descriptor */ | /* Create and intialize new connection descriptor */ | ||||
con = ng_l2cap_new_con(l2cap, bdaddr); | con = ng_l2cap_new_con(l2cap, bdaddr, type); | ||||
if (con == NULL) | if (con == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
/* Create and send LP_ConnectReq event */ | /* Create and send LP_ConnectReq event */ | ||||
NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_CON_REQ, | NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_CON_REQ, | ||||
sizeof(*ep), M_NOWAIT); | sizeof(*ep), M_NOWAIT); | ||||
if (msg == NULL) { | if (msg == NULL) { | ||||
ng_l2cap_free_con(con); | ng_l2cap_free_con(con); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
ep = (ng_hci_lp_con_req_ep *) (msg->data); | ep = (ng_hci_lp_con_req_ep *) (msg->data); | ||||
bcopy(bdaddr, &ep->bdaddr, sizeof(ep->bdaddr)); | bcopy(bdaddr, &ep->bdaddr, sizeof(ep->bdaddr)); | ||||
ep->link_type = NG_HCI_LINK_ACL; | ep->link_type = type; | ||||
con->flags |= NG_L2CAP_CON_OUTGOING; | con->flags |= NG_L2CAP_CON_OUTGOING; | ||||
con->state = NG_L2CAP_W4_LP_CON_CFM; | con->state = NG_L2CAP_W4_LP_CON_CFM; | ||||
ng_l2cap_lp_timeout(con); | ng_l2cap_lp_timeout(con); | ||||
NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, 0); | NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, 0); | ||||
if (error != 0) { | if (error != 0) { | ||||
if (ng_l2cap_lp_untimeout(con) == 0) | if (ng_l2cap_lp_untimeout(con) == 0) | ||||
Show All 27 Lines | if (msg->header.arglen != sizeof(*ep)) { | ||||
NG_L2CAP_ALERT( | NG_L2CAP_ALERT( | ||||
"%s: %s - invalid LP_ConnectCfm[Neg] message size\n", | "%s: %s - invalid LP_ConnectCfm[Neg] message size\n", | ||||
__func__, NG_NODE_NAME(l2cap->node)); | __func__, NG_NODE_NAME(l2cap->node)); | ||||
error = EMSGSIZE; | error = EMSGSIZE; | ||||
goto out; | goto out; | ||||
} | } | ||||
ep = (ng_hci_lp_con_cfm_ep *) (msg->data); | ep = (ng_hci_lp_con_cfm_ep *) (msg->data); | ||||
/* Check if we have requested/accepted this connection */ | /* Check if we have requested/accepted this connection */ | ||||
con = ng_l2cap_con_by_addr(l2cap, &ep->bdaddr); | con = ng_l2cap_con_by_addr(l2cap, &ep->bdaddr, ep->link_type); | ||||
if (con == NULL) { | if (con == NULL) { | ||||
NG_L2CAP_ERR( | NG_L2CAP_ERR( | ||||
"%s: %s - unexpected LP_ConnectCfm event. Connection does not exist\n", | "%s: %s - unexpected LP_ConnectCfm event. Connection does not exist\n", | ||||
__func__, NG_NODE_NAME(l2cap->node)); | __func__, NG_NODE_NAME(l2cap->node)); | ||||
error = ENOENT; | error = ENOENT; | ||||
goto out; | goto out; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | "%s: %s - invalid LP_ConnectInd message size\n", | ||||
__func__, NG_NODE_NAME(l2cap->node)); | __func__, NG_NODE_NAME(l2cap->node)); | ||||
return (EMSGSIZE); | return (EMSGSIZE); | ||||
} | } | ||||
ep = (ng_hci_lp_con_ind_ep *) (msg->data); | ep = (ng_hci_lp_con_ind_ep *) (msg->data); | ||||
/* Make sure we have only one connection to the remote unit */ | /* Make sure we have only one connection to the remote unit */ | ||||
con = ng_l2cap_con_by_addr(l2cap, &ep->bdaddr); | con = ng_l2cap_con_by_addr(l2cap, &ep->bdaddr, ep->link_type); | ||||
if (con != NULL) { | if (con != NULL) { | ||||
NG_L2CAP_ALERT( | NG_L2CAP_ALERT( | ||||
"%s: %s - unexpected LP_ConnectInd event. " \ | "%s: %s - unexpected LP_ConnectInd event. " \ | ||||
"Connection already exists, state=%d, con_handle=%d\n", | "Connection already exists, state=%d, con_handle=%d\n", | ||||
__func__, NG_NODE_NAME(l2cap->node), con->state, | __func__, NG_NODE_NAME(l2cap->node), con->state, | ||||
con->con_handle); | con->con_handle); | ||||
return (EEXIST); | return (EEXIST); | ||||
} | } | ||||
/* Check if lower layer protocol is still connected */ | /* Check if lower layer protocol is still connected */ | ||||
if (l2cap->hci == NULL || NG_HOOK_NOT_VALID(l2cap->hci)) { | if (l2cap->hci == NULL || NG_HOOK_NOT_VALID(l2cap->hci)) { | ||||
NG_L2CAP_ERR( | NG_L2CAP_ERR( | ||||
"%s: %s - hook \"%s\" is not connected or valid", | "%s: %s - hook \"%s\" is not connected or valid", | ||||
__func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI); | __func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI); | ||||
return (ENOTCONN); | return (ENOTCONN); | ||||
} | } | ||||
/* Create and intialize new connection descriptor */ | /* Create and intialize new connection descriptor */ | ||||
con = ng_l2cap_new_con(l2cap, &ep->bdaddr); | con = ng_l2cap_new_con(l2cap, &ep->bdaddr, ep->link_type); | ||||
if (con == NULL) | if (con == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
/* Create and send LP_ConnectRsp event */ | /* Create and send LP_ConnectRsp event */ | ||||
NG_MKMESSAGE(rsp, NGM_HCI_COOKIE, NGM_HCI_LP_CON_RSP, | NG_MKMESSAGE(rsp, NGM_HCI_COOKIE, NGM_HCI_LP_CON_RSP, | ||||
sizeof(*rp), M_NOWAIT); | sizeof(*rp), M_NOWAIT); | ||||
if (rsp == NULL) { | if (rsp == NULL) { | ||||
ng_l2cap_free_con(con); | ng_l2cap_free_con(con); | ||||
▲ Show 20 Lines • Show All 511 Lines • ▼ Show 20 Lines | "%s: %s - hook \"%s\" is not connected or valid", | ||||
} | } | ||||
/* Send ACL data packets */ | /* Send ACL data packets */ | ||||
while (con->pending < con->l2cap->num_pkts && con->tx_pkt != NULL) { | while (con->pending < con->l2cap->num_pkts && con->tx_pkt != NULL) { | ||||
m = con->tx_pkt; | m = con->tx_pkt; | ||||
con->tx_pkt = con->tx_pkt->m_nextpkt; | con->tx_pkt = con->tx_pkt->m_nextpkt; | ||||
m->m_nextpkt = NULL; | m->m_nextpkt = NULL; | ||||
if(m->m_flags &M_PROTO2){ | |||||
ng_l2cap_lp_receive(con->l2cap, m); | |||||
continue; | |||||
} | |||||
emax: can you please explain why this is needed? is there no indication for received responses here? | |||||
Not Done Inline ActionsIt simulates L2CAP connection complete when HCI connection established. takawata: It simulates L2CAP connection complete when HCI connection established.
When it established… | |||||
Not Done Inline Actionsi'm sorry, but i'm completely lost here. ng_l2ap_lp_deliver() sends data to the HCI layer. ng_l2cap_lp_receive() receives data from the HCI layer. so, if i'm reading this right, the code tries to loopback some special packet marked with M_PROTO2 flag. instead of doing that, would it be possible to adjust state in upper layer and not send effectively dummy command down to l2cap layer? emax: i'm sorry, but i'm completely lost here. ng_l2ap_lp_deliver() sends data to the HCI layer. | |||||
Not Done Inline ActionsI want to know when the packet processing start here, so state transition at caller is not desirable. And I used mbuf flag because I don't want to peek packet content here. takawata: I want to know when the packet processing start here, so state transition at caller is not… | |||||
emaxUnsubmitted Not Done Inline Actionscan you please explain why loopback it here? is it not possible to loopback command at the socket layer? emax: can you please explain why loopback it here? is it not possible to loopback command at the… | |||||
takawataAuthorUnsubmitted Not Done Inline ActionsTo wait HCI connection event. Otherwise, it may possible to add outstanding ATT channel pointer to connection structure and change channel states if the channel pointer is valid. takawata: To wait HCI connection event. Otherwise, it may possible to add outstanding ATT channel pointer… | |||||
NG_L2CAP_INFO( | NG_L2CAP_INFO( | ||||
"%s: %s - sending ACL packet, con_handle=%d, len=%d\n", | "%s: %s - sending ACL packet, con_handle=%d, len=%d\n", | ||||
__func__, NG_NODE_NAME(l2cap->node), con->con_handle, | __func__, NG_NODE_NAME(l2cap->node), con->con_handle, | ||||
m->m_pkthdr.len); | m->m_pkthdr.len); | ||||
NG_SEND_DATA_ONLY(error, l2cap->hci, m); | NG_SEND_DATA_ONLY(error, l2cap->hci, m); | ||||
if (error != 0) { | if (error != 0) { | ||||
NG_L2CAP_ERR( | NG_L2CAP_ERR( | ||||
▲ Show 20 Lines • Show All 129 Lines • Show Last 20 Lines |
can you please explain why this is needed? is there no indication for received responses here?