svn commit: r281198 - in head/sys/netgraph/bluetooth: hci include l2cap socket
Takanori Watanabe
takawata at FreeBSD.org
Tue Apr 7 10:23:01 UTC 2015
Author: takawata
Date: Tue Apr 7 10:22:56 2015
New Revision: 281198
URL: https://svnweb.freebsd.org/changeset/base/281198
Log:
Initial Bluetooth LE support.
Note that sockaddr_l2cap structure is changed , check socket address
to initialize new structure member and define L2CAP_SOCKET_CHECKED
before including ng_btsocket.h
Differential Revision: https://reviews.freebsd.org/D2021
Reviewed by:emax
Modified:
head/sys/netgraph/bluetooth/hci/ng_hci_cmds.c
head/sys/netgraph/bluetooth/hci/ng_hci_evnt.c
head/sys/netgraph/bluetooth/hci/ng_hci_main.c
head/sys/netgraph/bluetooth/hci/ng_hci_misc.c
head/sys/netgraph/bluetooth/hci/ng_hci_misc.h
head/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c
head/sys/netgraph/bluetooth/hci/ng_hci_var.h
head/sys/netgraph/bluetooth/include/ng_btsocket.h
head/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
head/sys/netgraph/bluetooth/include/ng_hci.h
head/sys/netgraph/bluetooth/include/ng_l2cap.h
head/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.c
head/sys/netgraph/bluetooth/l2cap/ng_l2cap_cmds.h
head/sys/netgraph/bluetooth/l2cap/ng_l2cap_evnt.c
head/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c
head/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.h
head/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.c
head/sys/netgraph/bluetooth/l2cap/ng_l2cap_misc.h
head/sys/netgraph/bluetooth/l2cap/ng_l2cap_ulpi.c
head/sys/netgraph/bluetooth/l2cap/ng_l2cap_var.h
head/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c
head/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
head/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c
Modified: head/sys/netgraph/bluetooth/hci/ng_hci_cmds.c
==============================================================================
--- head/sys/netgraph/bluetooth/hci/ng_hci_cmds.c Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/hci/ng_hci_cmds.c Tue Apr 7 10:22:56 2015 (r281198)
@@ -71,11 +71,15 @@ static int process_status_params
(ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
static int process_testing_params
(ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
+static int process_le_params
+ (ng_hci_unit_p, u_int16_t, struct mbuf *, struct mbuf *);
static int process_link_control_status
(ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
static int process_link_policy_status
(ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
+static int process_le_status
+ (ng_hci_unit_p, ng_hci_command_status_ep *, struct mbuf *);
/*
* Send HCI command to the driver.
@@ -222,7 +226,10 @@ ng_hci_process_command_complete(ng_hci_u
error = process_testing_params(unit,
NG_HCI_OCF(ep->opcode), cp, e);
break;
-
+ case NG_HCI_OGF_LE:
+ error = process_le_params(unit,
+ NG_HCI_OCF(ep->opcode), cp, e);
+ break;
case NG_HCI_OGF_BT_LOGO:
case NG_HCI_OGF_VENDOR:
NG_FREE_M(cp);
@@ -294,7 +301,9 @@ ng_hci_process_command_status(ng_hci_uni
case NG_HCI_OGF_LINK_POLICY:
error = process_link_policy_status(unit, ep, cp);
break;
-
+ case NG_HCI_OGF_LE:
+ error = process_le_status(unit, ep, cp);
+ break;
case NG_HCI_OGF_BT_LOGO:
case NG_HCI_OGF_VENDOR:
NG_FREE_M(cp);
@@ -604,6 +613,8 @@ process_hc_baseband_params(ng_hci_unit_p
case NG_HCI_OCF_READ_LOCAL_NAME:
case NG_HCI_OCF_READ_UNIT_CLASS:
case NG_HCI_OCF_WRITE_UNIT_CLASS:
+ case NG_HCI_OCF_READ_LE_HOST_SUPPORTED:
+ case NG_HCI_OCF_WRITE_LE_HOST_SUPPORTED:
/* These do not need post processing */
break;
@@ -796,6 +807,132 @@ process_testing_params(ng_hci_unit_p uni
return (error);
} /* process_testing_params */
+/*
+ * Process LE command return parameters
+ */
+
+static int
+process_le_params(ng_hci_unit_p unit, u_int16_t ocf,
+ struct mbuf *mcp, struct mbuf *mrp)
+{
+ int error = 0;
+
+ switch (ocf){
+ case NG_HCI_OCF_LE_SET_EVENT_MASK:
+ case NG_HCI_OCF_LE_READ_BUFFER_SIZE:
+ case NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES:
+ case NG_HCI_OCF_LE_SET_RANDOM_ADDRESS:
+ case NG_HCI_OCF_LE_SET_ADVERTISING_PARAMETERS:
+ case NG_HCI_OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER:
+ case NG_HCI_OCF_LE_SET_ADVERTISING_DATA:
+ case NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA:
+ case NG_HCI_OCF_LE_SET_ADVERTISE_ENABLE:
+ case NG_HCI_OCF_LE_SET_SCAN_PARAMETERS:
+ case NG_HCI_OCF_LE_SET_SCAN_ENABLE:
+ case NG_HCI_OCF_LE_CREATE_CONNECTION_CANCEL:
+ case NG_HCI_OCF_LE_CLEAR_WHITE_LIST:
+ case NG_HCI_OCF_LE_READ_WHITE_LIST_SIZE:
+ case NG_HCI_OCF_LE_ADD_DEVICE_TO_WHITE_LIST:
+ case NG_HCI_OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST:
+ case NG_HCI_OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION:
+ case NG_HCI_OCF_LE_READ_CHANNEL_MAP:
+ case NG_HCI_OCF_LE_ENCRYPT:
+ case NG_HCI_OCF_LE_RAND:
+ case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_REPLY:
+ case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY:
+ case NG_HCI_OCF_LE_READ_SUPPORTED_STATUS:
+ case NG_HCI_OCF_LE_RECEIVER_TEST:
+ case NG_HCI_OCF_LE_TRANSMITTER_TEST:
+ case NG_HCI_OCF_LE_TEST_END:
+
+ /* These do not need post processing */
+ break;
+ case NG_HCI_OCF_LE_CREATE_CONNECTION:
+ case NG_HCI_OCF_LE_CONNECTION_UPDATE:
+ case NG_HCI_OCF_LE_READ_REMOTE_USED_FEATURES:
+ case NG_HCI_OCF_LE_START_ENCRYPTION:
+
+
+ default:
+ /*
+ * None of these command was supposed to generate
+ * Command_Complete event. Instead Command_Status event
+ * should have been generated and then appropriate event
+ * should have been sent to indicate the final result.
+ */
+
+ error = EINVAL;
+ break;
+ }
+
+ NG_FREE_M(mcp);
+ NG_FREE_M(mrp);
+
+ return (error);
+
+}
+
+
+
+static int
+process_le_status(ng_hci_unit_p unit,ng_hci_command_status_ep *ep,
+ struct mbuf *mcp)
+{
+ int error = 0;
+
+ switch (NG_HCI_OCF(ep->opcode)){
+ case NG_HCI_OCF_LE_CREATE_CONNECTION:
+ case NG_HCI_OCF_LE_CONNECTION_UPDATE:
+ case NG_HCI_OCF_LE_READ_REMOTE_USED_FEATURES:
+ case NG_HCI_OCF_LE_START_ENCRYPTION:
+
+ /* These do not need post processing */
+ break;
+
+ case NG_HCI_OCF_LE_SET_EVENT_MASK:
+ case NG_HCI_OCF_LE_READ_BUFFER_SIZE:
+ case NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES:
+ case NG_HCI_OCF_LE_SET_RANDOM_ADDRESS:
+ case NG_HCI_OCF_LE_SET_ADVERTISING_PARAMETERS:
+ case NG_HCI_OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER:
+ case NG_HCI_OCF_LE_SET_ADVERTISING_DATA:
+ case NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA:
+ case NG_HCI_OCF_LE_SET_ADVERTISE_ENABLE:
+ case NG_HCI_OCF_LE_SET_SCAN_PARAMETERS:
+ case NG_HCI_OCF_LE_SET_SCAN_ENABLE:
+ case NG_HCI_OCF_LE_CREATE_CONNECTION_CANCEL:
+ case NG_HCI_OCF_LE_CLEAR_WHITE_LIST:
+ case NG_HCI_OCF_LE_READ_WHITE_LIST_SIZE:
+ case NG_HCI_OCF_LE_ADD_DEVICE_TO_WHITE_LIST:
+ case NG_HCI_OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST:
+ case NG_HCI_OCF_LE_SET_HOST_CHANNEL_CLASSIFICATION:
+ case NG_HCI_OCF_LE_READ_CHANNEL_MAP:
+ case NG_HCI_OCF_LE_ENCRYPT:
+ case NG_HCI_OCF_LE_RAND:
+ case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_REPLY:
+ case NG_HCI_OCF_LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY:
+ case NG_HCI_OCF_LE_READ_SUPPORTED_STATUS:
+ case NG_HCI_OCF_LE_RECEIVER_TEST:
+ case NG_HCI_OCF_LE_TRANSMITTER_TEST:
+ case NG_HCI_OCF_LE_TEST_END:
+
+
+ default:
+ /*
+ * None of these command was supposed to generate
+ * Command_Stutus event. Command Complete instead.
+ */
+
+ error = EINVAL;
+ break;
+ }
+
+ NG_FREE_M(mcp);
+
+ return (error);
+
+}
+
/*
* Process link control command status
*/
Modified: head/sys/netgraph/bluetooth/hci/ng_hci_evnt.c
==============================================================================
--- head/sys/netgraph/bluetooth/hci/ng_hci_evnt.c Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/hci/ng_hci_evnt.c Tue Apr 7 10:22:56 2015 (r281198)
@@ -76,6 +76,7 @@ static int page_scan_mode_change (n
static int page_scan_rep_mode_change (ng_hci_unit_p, struct mbuf *);
static int sync_con_queue (ng_hci_unit_p, ng_hci_unit_con_p, int);
static int send_data_packets (ng_hci_unit_p, int, int);
+static int le_event (ng_hci_unit_p, struct mbuf *);
/*
* Process HCI event packet
@@ -121,6 +122,9 @@ ng_hci_process_event(ng_hci_unit_p unit,
/* These do not need post processing */
NG_FREE_M(event);
break;
+ case NG_HCI_EVENT_LE:
+ error = le_event(unit, event);
+ break;
case NG_HCI_EVENT_INQUIRY_RESULT:
error = inquiry_result(unit, event);
@@ -247,6 +251,7 @@ static int
send_data_packets(ng_hci_unit_p unit, int link_type, int limit)
{
ng_hci_unit_con_p con = NULL, winner = NULL;
+ int reallink_type;
item_p item = NULL;
int min_pending, total_sent, sent, error, v;
@@ -260,8 +265,11 @@ send_data_packets(ng_hci_unit_p unit, in
*/
LIST_FOREACH(con, &unit->con_list, next) {
- if (con->link_type != link_type)
+ reallink_type = (con->link_type == NG_HCI_LINK_SCO)?
+ NG_HCI_LINK_SCO: NG_HCI_LINK_ACL;
+ if (reallink_type != link_type){
continue;
+ }
if (NG_BT_ITEMQ_LEN(&con->conq) == 0)
continue;
@@ -327,7 +335,6 @@ send_data_packets(ng_hci_unit_p unit, in
/*
* Sync connection queue for the winner
*/
-
sync_con_queue(unit, winner, sent);
}
@@ -346,7 +353,7 @@ sync_con_queue(ng_hci_unit_p unit, ng_hc
ng_hci_sync_con_queue_ep *state = NULL;
int error;
- hook = (con->link_type == NG_HCI_LINK_ACL)? unit->acl : unit->sco;
+ hook = (con->link_type != NG_HCI_LINK_SCO)? unit->acl : unit->sco;
if (hook == NULL || NG_HOOK_NOT_VALID(hook))
return (ENOTCONN);
@@ -363,6 +370,223 @@ sync_con_queue(ng_hci_unit_p unit, ng_hc
return (error);
} /* sync_con_queue */
+/* le meta event */
+/* Inquiry result event */
+static int
+le_advertizing_report(ng_hci_unit_p unit, struct mbuf *event)
+{
+ ng_hci_le_advertising_report_ep *ep = NULL;
+ ng_hci_neighbor_p n = NULL;
+ bdaddr_t bdaddr;
+ int error = 0;
+ u_int8_t event_type;
+ u_int8_t addr_type;
+
+ NG_HCI_M_PULLUP(event, sizeof(*ep));
+ if (event == NULL)
+ return (ENOBUFS);
+
+ ep = mtod(event, ng_hci_le_advertising_report_ep *);
+ m_adj(event, sizeof(*ep));
+
+ for (; ep->num_reports > 0; ep->num_reports --) {
+ /* Get remote unit address */
+ NG_HCI_M_PULLUP(event, sizeof(u_int8_t));
+ event_type = *mtod(event, u_int8_t *);
+ m_adj(event, sizeof(u_int8_t));
+ NG_HCI_M_PULLUP(event, sizeof(u_int8_t));
+ addr_type = *mtod(event, u_int8_t *);
+ m_adj(event, sizeof(u_int8_t));
+
+ m_copydata(event, 0, sizeof(bdaddr), (caddr_t) &bdaddr);
+ m_adj(event, sizeof(bdaddr));
+
+ /* Lookup entry in the cache */
+ n = ng_hci_get_neighbor(unit, &bdaddr, (addr_type) ? NG_HCI_LINK_LE_RANDOM:NG_HCI_LINK_LE_PUBLIC);
+ if (n == NULL) {
+ /* Create new entry */
+ n = ng_hci_new_neighbor(unit);
+ if (n == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bcopy(&bdaddr, &n->bdaddr, sizeof(n->bdaddr));
+ n->addrtype = (addr_type)? NG_HCI_LINK_LE_RANDOM :
+ NG_HCI_LINK_LE_PUBLIC;
+
+ } else
+ getmicrotime(&n->updated);
+
+#if 0
+ {
+ /*
+ * TODO: Make these information
+ * Available from userland.
+ */
+ u_int8_t length_data;
+
+ char *rssi;
+
+ NG_HCI_M_PULLUP(event, sizeof(u_int8_t));
+ length_data = *mtod(event, u_int8_t *);
+ m_adj(event, sizeof(u_int8_t));
+ /*Advertizement data*/
+ NG_HCI_M_PULLUP(event, length_data);
+ m_adj(event, length_data);
+ NG_HCI_M_PULLUP(event, sizeof(char ));
+ /*Get RSSI*/
+ rssi = mtod(event, char *);
+ m_adj(event, sizeof(u_int8_t));
+ }
+#endif
+ }
+ NG_FREE_M(event);
+
+ return (error);
+} /* inquiry_result */
+
+static int le_connection_complete(ng_hci_unit_p unit, struct mbuf *event)
+{
+ int error = 0;
+
+ ng_hci_le_connection_complete_ep *ep = NULL;
+ ng_hci_unit_con_p con = NULL;
+ int link_type;
+ uint8_t uclass[3] = {0,0,0};//dummy uclass
+
+ NG_HCI_M_PULLUP(event, sizeof(*ep));
+ if (event == NULL)
+ return (ENOBUFS);
+
+ ep = mtod(event, ng_hci_le_connection_complete_ep *);
+ link_type = (ep->address_type)? NG_HCI_LINK_LE_RANDOM :
+ NG_HCI_LINK_LE_PUBLIC;
+ /*
+ * Find the first connection descriptor that matches the following:
+ *
+ * 1) con->link_type == link_type
+ * 2) con->state == NG_HCI_CON_W4_CONN_COMPLETE
+ * 3) con->bdaddr == ep->address
+ */
+ LIST_FOREACH(con, &unit->con_list, next)
+ if (con->link_type == link_type &&
+ con->state == NG_HCI_CON_W4_CONN_COMPLETE &&
+ bcmp(&con->bdaddr, &ep->address, sizeof(bdaddr_t)) == 0)
+ break;
+
+ /*
+ * Two possible cases:
+ *
+ * 1) We have found connection descriptor. That means upper layer has
+ * requested this connection via LP_CON_REQ message. In this case
+ * connection must have timeout set. If ng_hci_con_untimeout() fails
+ * then timeout message already went into node's queue. In this case
+ * ignore Connection_Complete event and let timeout deal with it.
+ *
+ * 2) We do not have connection descriptor. That means upper layer
+ * nas not requested this connection , (less likely) we gave up
+ * on this connection (timeout) or as node act as slave role.
+ * The most likely scenario is that
+ * we have received LE_Create_Connection command
+ * from the RAW hook
+ */
+
+ if (con == NULL) {
+ if (ep->status != 0)
+ goto out;
+
+ con = ng_hci_new_con(unit, link_type);
+ if (con == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ con->state = NG_HCI_CON_W4_LP_CON_RSP;
+ ng_hci_con_timeout(con);
+
+ bcopy(&ep->address, &con->bdaddr, sizeof(con->bdaddr));
+ error = ng_hci_lp_con_ind(con, uclass);
+ if (error != 0) {
+ ng_hci_con_untimeout(con);
+ ng_hci_free_con(con);
+ }
+
+ } else if ((error = ng_hci_con_untimeout(con)) != 0)
+ goto out;
+
+ /*
+ * Update connection descriptor and send notification
+ * to the upper layers.
+ */
+
+ con->con_handle = NG_HCI_CON_HANDLE(le16toh(ep->handle));
+ con->encryption_mode = NG_HCI_ENCRYPTION_MODE_NONE;
+
+ ng_hci_lp_con_cfm(con, ep->status);
+
+ /* Adjust connection state */
+ if (ep->status != 0)
+ ng_hci_free_con(con);
+ else {
+ con->state = NG_HCI_CON_OPEN;
+
+ /*
+ * Change link policy for the ACL connections. Enable all
+ * supported link modes. Enable Role switch as well if
+ * device supports it.
+ */
+
+ }
+
+out:
+ NG_FREE_M(event);
+
+ return (error);
+
+}
+
+static int le_connection_update(ng_hci_unit_p unit, struct mbuf *event)
+{
+ int error = 0;
+ /*TBD*/
+
+ NG_FREE_M(event);
+ return error;
+
+}
+static int
+le_event(ng_hci_unit_p unit, struct mbuf *event)
+{
+ int error = 0;
+ ng_hci_le_ep *lep;
+
+ NG_HCI_M_PULLUP(event, sizeof(*lep));
+ if(event ==NULL){
+ return ENOBUFS;
+ }
+ lep = mtod(event, ng_hci_le_ep *);
+ m_adj(event, sizeof(*lep));
+ switch(lep->subevent_code){
+ case NG_HCI_LEEV_CON_COMPL:
+ le_connection_complete(unit, event);
+ break;
+ case NG_HCI_LEEV_ADVREP:
+ le_advertizing_report(unit, event);
+ break;
+ case NG_HCI_LEEV_CON_UPDATE_COMPL:
+ le_connection_update(unit, event);
+ break;
+ case NG_HCI_LEEV_READ_REMOTE_FEATURES_COMPL:
+ //TBD
+ /*FALLTHROUGH*/
+ case NG_HCI_LEEV_LONG_TERM_KEY_REQUEST:
+ //TBD
+ /*FALLTHROUGH*/
+ default:
+ NG_FREE_M(event);
+ }
+ return error;
+}
/* Inquiry result event */
static int
@@ -386,7 +610,7 @@ inquiry_result(ng_hci_unit_p unit, struc
m_adj(event, sizeof(bdaddr));
/* Lookup entry in the cache */
- n = ng_hci_get_neighbor(unit, &bdaddr);
+ n = ng_hci_get_neighbor(unit, &bdaddr, NG_HCI_LINK_ACL);
if (n == NULL) {
/* Create new entry */
n = ng_hci_new_neighbor(unit);
@@ -398,6 +622,7 @@ inquiry_result(ng_hci_unit_p unit, struc
getmicrotime(&n->updated);
bcopy(&bdaddr, &n->bdaddr, sizeof(n->bdaddr));
+ n->addrtype = NG_HCI_LINK_ACL;
/* XXX call m_pullup here? */
@@ -754,7 +979,7 @@ read_remote_features_compl(ng_hci_unit_p
}
/* Update cache entry */
- n = ng_hci_get_neighbor(unit, &con->bdaddr);
+ n = ng_hci_get_neighbor(unit, &con->bdaddr, NG_HCI_LINK_ACL);
if (n == NULL) {
n = ng_hci_new_neighbor(unit);
if (n == NULL) {
@@ -763,6 +988,7 @@ read_remote_features_compl(ng_hci_unit_p
}
bcopy(&con->bdaddr, &n->bdaddr, sizeof(n->bdaddr));
+ n->addrtype = NG_HCI_LINK_ACL;
} else
getmicrotime(&n->updated);
@@ -909,7 +1135,7 @@ num_compl_pkts(ng_hci_unit_p unit, struc
}
/* Update buffer descriptor */
- if (con->link_type == NG_HCI_LINK_ACL)
+ if (con->link_type != NG_HCI_LINK_SCO)
NG_HCI_BUFF_ACL_FREE(unit->buffer, p);
else
NG_HCI_BUFF_SCO_FREE(unit->buffer, p);
@@ -1010,7 +1236,7 @@ read_clock_offset_compl(ng_hci_unit_p un
}
/* Update cache entry */
- n = ng_hci_get_neighbor(unit, &con->bdaddr);
+ n = ng_hci_get_neighbor(unit, &con->bdaddr, NG_HCI_LINK_ACL);
if (n == NULL) {
n = ng_hci_new_neighbor(unit);
if (n == NULL) {
@@ -1019,6 +1245,7 @@ read_clock_offset_compl(ng_hci_unit_p un
}
bcopy(&con->bdaddr, &n->bdaddr, sizeof(n->bdaddr));
+ n->addrtype = NG_HCI_LINK_ACL;
} else
getmicrotime(&n->updated);
@@ -1089,7 +1316,7 @@ page_scan_mode_change(ng_hci_unit_p unit
ep = mtod(event, ng_hci_page_scan_mode_change_ep *);
/* Update cache entry */
- n = ng_hci_get_neighbor(unit, &ep->bdaddr);
+ n = ng_hci_get_neighbor(unit, &ep->bdaddr, NG_HCI_LINK_ACL);
if (n == NULL) {
n = ng_hci_new_neighbor(unit);
if (n == NULL) {
@@ -1098,6 +1325,7 @@ page_scan_mode_change(ng_hci_unit_p unit
}
bcopy(&ep->bdaddr, &n->bdaddr, sizeof(n->bdaddr));
+ n->addrtype = NG_HCI_LINK_ACL;
} else
getmicrotime(&n->updated);
@@ -1123,7 +1351,7 @@ page_scan_rep_mode_change(ng_hci_unit_p
ep = mtod(event, ng_hci_page_scan_rep_mode_change_ep *);
/* Update cache entry */
- n = ng_hci_get_neighbor(unit, &ep->bdaddr);
+ n = ng_hci_get_neighbor(unit, &ep->bdaddr, NG_HCI_LINK_ACL);
if (n == NULL) {
n = ng_hci_new_neighbor(unit);
if (n == NULL) {
@@ -1132,6 +1360,7 @@ page_scan_rep_mode_change(ng_hci_unit_p
}
bcopy(&ep->bdaddr, &n->bdaddr, sizeof(n->bdaddr));
+ n->addrtype = NG_HCI_LINK_ACL;
} else
getmicrotime(&n->updated);
Modified: head/sys/netgraph/bluetooth/hci/ng_hci_main.c
==============================================================================
--- head/sys/netgraph/bluetooth/hci/ng_hci_main.c Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/hci/ng_hci_main.c Tue Apr 7 10:22:56 2015 (r281198)
@@ -775,7 +775,6 @@ ng_hci_acl_rcvdata(hook_p hook, item_p i
int size, error = 0;
NG_HCI_BUFF_ACL_SIZE(unit->buffer, size);
-
/* Check packet */
NGI_GET_M(item, m);
@@ -788,7 +787,6 @@ ng_hci_acl_rcvdata(hook_p hook, item_p i
error = EINVAL;
goto drop;
}
-
if (m->m_pkthdr.len < sizeof(ng_hci_acldata_pkt_t) ||
m->m_pkthdr.len > sizeof(ng_hci_acldata_pkt_t) + size) {
NG_HCI_ALERT(
@@ -831,7 +829,7 @@ ng_hci_acl_rcvdata(hook_p hook, item_p i
goto drop;
}
- if (con->link_type != NG_HCI_LINK_ACL) {
+ if (con->link_type == NG_HCI_LINK_SCO) {
NG_HCI_ERR(
"%s: %s - unexpected HCI ACL data packet. Not ACL link, con_handle=%d, " \
"link_type=%d\n", __func__, NG_NODE_NAME(unit->node),
Modified: head/sys/netgraph/bluetooth/hci/ng_hci_misc.c
==============================================================================
--- head/sys/netgraph/bluetooth/hci/ng_hci_misc.c Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/hci/ng_hci_misc.c Tue Apr 7 10:22:56 2015 (r281198)
@@ -214,7 +214,7 @@ ng_hci_flush_neighbor_cache(ng_hci_unit_
*/
ng_hci_neighbor_p
-ng_hci_get_neighbor(ng_hci_unit_p unit, bdaddr_p bdaddr)
+ng_hci_get_neighbor(ng_hci_unit_p unit, bdaddr_p bdaddr,int link_type)
{
ng_hci_neighbor_p n = NULL;
@@ -222,7 +222,8 @@ ng_hci_get_neighbor(ng_hci_unit_p unit,
ng_hci_neighbor_p nn = LIST_NEXT(n, next);
if (!ng_hci_neighbor_stale(n)) {
- if (bcmp(&n->bdaddr, bdaddr, sizeof(*bdaddr)) == 0)
+ if (n->addrtype == link_type &&
+ bcmp(&n->bdaddr, bdaddr, sizeof(*bdaddr)) == 0)
break;
} else
ng_hci_free_neighbor(n); /* remove old entry */
@@ -284,7 +285,7 @@ ng_hci_new_con(ng_hci_unit_p unit, int l
con->link_type = link_type;
- if (con->link_type == NG_HCI_LINK_ACL)
+ if (con->link_type != NG_HCI_LINK_SCO)
NG_HCI_BUFF_ACL_TOTAL(unit->buffer, num_pkts);
else
NG_HCI_BUFF_SCO_TOTAL(unit->buffer, num_pkts);
@@ -313,7 +314,7 @@ ng_hci_free_con(ng_hci_unit_con_p con)
* flushed these packets and we can free them too
*/
- if (con->link_type == NG_HCI_LINK_ACL)
+ if (con->link_type != NG_HCI_LINK_SCO)
NG_HCI_BUFF_ACL_FREE(con->unit->buffer, con->pending);
else
NG_HCI_BUFF_SCO_FREE(con->unit->buffer, con->pending);
Modified: head/sys/netgraph/bluetooth/hci/ng_hci_misc.h
==============================================================================
--- head/sys/netgraph/bluetooth/hci/ng_hci_misc.h Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/hci/ng_hci_misc.h Tue Apr 7 10:22:56 2015 (r281198)
@@ -41,7 +41,7 @@ void ng_hci_unit_clean
ng_hci_neighbor_p ng_hci_new_neighbor (ng_hci_unit_p);
void ng_hci_free_neighbor (ng_hci_neighbor_p);
void ng_hci_flush_neighbor_cache (ng_hci_unit_p);
-ng_hci_neighbor_p ng_hci_get_neighbor (ng_hci_unit_p, bdaddr_p);
+ng_hci_neighbor_p ng_hci_get_neighbor (ng_hci_unit_p, bdaddr_p, int);
int ng_hci_neighbor_stale (ng_hci_neighbor_p);
ng_hci_unit_con_p ng_hci_new_con (ng_hci_unit_p, int);
Modified: head/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c
==============================================================================
--- head/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/hci/ng_hci_ulpi.c Tue Apr 7 10:22:56 2015 (r281198)
@@ -56,6 +56,7 @@
static int ng_hci_lp_acl_con_req (ng_hci_unit_p, item_p, hook_p);
static int ng_hci_lp_sco_con_req (ng_hci_unit_p, item_p, hook_p);
+static int ng_hci_lp_le_con_req (ng_hci_unit_p, item_p, hook_p, int);
/*
* Process LP_ConnectReq event from the upper layer protocol
@@ -64,6 +65,8 @@ static int ng_hci_lp_sco_con_req (ng_hci
int
ng_hci_lp_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
{
+ int link_type;
+
if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY) {
NG_HCI_WARN(
"%s: %s - unit is not ready, state=%#x\n",
@@ -84,21 +87,30 @@ ng_hci_lp_con_req(ng_hci_unit_p unit, it
return (EMSGSIZE);
}
-
- if (((ng_hci_lp_con_req_ep *)(NGI_MSG(item)->data))->link_type == NG_HCI_LINK_ACL)
+ link_type = ((ng_hci_lp_con_req_ep *)(NGI_MSG(item)->data))->link_type;
+ switch(link_type){
+ case NG_HCI_LINK_ACL:
return (ng_hci_lp_acl_con_req(unit, item, hook));
-
- if (hook != unit->sco) {
- NG_HCI_WARN(
-"%s: %s - LP_ConnectReq for SCO connection came from wrong hook=%p\n",
- __func__, NG_NODE_NAME(unit->node), hook);
-
- NG_FREE_ITEM(item);
-
- return (EINVAL);
+ case NG_HCI_LINK_SCO:
+ if (hook != unit->sco ) {
+ NG_HCI_WARN(
+ "%s: %s - LP_ConnectReq for SCO connection came from wrong hook=%p\n",
+ __func__, NG_NODE_NAME(unit->node), hook);
+
+ NG_FREE_ITEM(item);
+
+ return (EINVAL);
+ }
+
+ return (ng_hci_lp_sco_con_req(unit, item, hook));
+ case NG_HCI_LINK_LE_PUBLIC:
+ case NG_HCI_LINK_LE_RANDOM:
+ return (ng_hci_lp_le_con_req(unit, item, hook, link_type));
+ default:
+ panic("%s: link_type invalid.", __func__);
}
-
- return (ng_hci_lp_sco_con_req(unit, item, hook));
+
+ return (EINVAL);
} /* ng_hci_lp_con_req */
/*
@@ -264,7 +276,7 @@ ng_hci_lp_acl_con_req(ng_hci_unit_p unit
* So check the neighbor cache.
*/
- n = ng_hci_get_neighbor(unit, &ep->bdaddr);
+ n = ng_hci_get_neighbor(unit, &ep->bdaddr, NG_HCI_LINK_ACL);
if (n == NULL) {
req->cp.page_scan_rep_mode = 0;
req->cp.page_scan_mode = 0;
@@ -469,6 +481,180 @@ out:
return (error);
} /* ng_hci_lp_sco_con_req */
+static int
+ng_hci_lp_le_con_req(ng_hci_unit_p unit, item_p item, hook_p hook, int link_type)
+{
+ struct acl_con_req {
+ ng_hci_cmd_pkt_t hdr;
+ ng_hci_le_create_connection_cp cp;
+ } __attribute__ ((packed)) *req = NULL;
+ ng_hci_lp_con_req_ep *ep = NULL;
+ ng_hci_unit_con_p con = NULL;
+ struct mbuf *m = NULL;
+ int error = 0;
+
+ ep = (ng_hci_lp_con_req_ep *)(NGI_MSG(item)->data);
+ if((link_type != NG_HCI_LINK_LE_PUBLIC)&&
+ (link_type != NG_HCI_LINK_LE_RANDOM)){
+ printf("%s: Link type %d Cannot be here \n", __func__,
+ link_type);
+ }
+ /*
+ * Only one ACL connection can exist between each pair of units.
+ * So try to find ACL connection descriptor (in any state) that
+ * has requested remote BD_ADDR.
+ *
+ * Two cases:
+ *
+ * 1) We do not have connection to the remote unit. This is simple.
+ * Just create new connection descriptor and send HCI command to
+ * create new connection.
+ *
+ * 2) We do have connection descriptor. We need to check connection
+ * state:
+ *
+ * 2.1) NG_HCI_CON_W4_LP_CON_RSP means that we are in the middle of
+ * accepting connection from the remote unit. This is a race
+ * condition. We will ignore this message.
+ *
+ * 2.2) NG_HCI_CON_W4_CONN_COMPLETE means that upper layer already
+ * requested connection or we just accepted it. In any case
+ * all we need to do here is set appropriate notification bit
+ * and wait.
+ *
+ * 2.3) NG_HCI_CON_OPEN means connection is open. Just reply back
+ * and let upper layer know that we have connection already.
+ */
+
+ con = ng_hci_con_by_bdaddr(unit, &ep->bdaddr, link_type);
+ if (con != NULL) {
+ switch (con->state) {
+ case NG_HCI_CON_W4_LP_CON_RSP: /* XXX */
+ error = EALREADY;
+ break;
+
+ case NG_HCI_CON_W4_CONN_COMPLETE:
+ if (hook != unit->sco)
+ con->flags |= NG_HCI_CON_NOTIFY_ACL;
+ else
+ con->flags |= NG_HCI_CON_NOTIFY_SCO;
+ break;
+
+ case NG_HCI_CON_OPEN: {
+ struct ng_mesg *msg = NULL;
+ ng_hci_lp_con_cfm_ep *cfm = NULL;
+
+ if (hook != NULL && NG_HOOK_IS_VALID(hook)) {
+ NGI_GET_MSG(item, msg);
+ NG_FREE_MSG(msg);
+
+ NG_MKMESSAGE(msg, NGM_HCI_COOKIE,
+ NGM_HCI_LP_CON_CFM, sizeof(*cfm),
+ M_NOWAIT);
+ if (msg != NULL) {
+ cfm = (ng_hci_lp_con_cfm_ep *)msg->data;
+ cfm->status = 0;
+ cfm->link_type = con->link_type;
+ cfm->con_handle = con->con_handle;
+ bcopy(&con->bdaddr, &cfm->bdaddr,
+ sizeof(cfm->bdaddr));
+
+ /*
+ * This will forward item back to
+ * sender and set item to NULL
+ */
+
+ _NGI_MSG(item) = msg;
+ NG_FWD_ITEM_HOOK(error, item, hook);
+ } else
+ error = ENOMEM;
+ } else
+ NG_HCI_INFO(
+"%s: %s - Source hook is not valid, hook=%p\n",
+ __func__, NG_NODE_NAME(unit->node),
+ hook);
+ } break;
+
+ default:
+ panic(
+"%s: %s - Invalid connection state=%d\n",
+ __func__, NG_NODE_NAME(unit->node), con->state);
+ break;
+ }
+
+ goto out;
+ }
+
+ /*
+ * If we got here then we need to create new ACL connection descriptor
+ * and submit HCI command. First create new connection desriptor, set
+ * bdaddr and notification flags.
+ */
+
+ con = ng_hci_new_con(unit, link_type);
+ if (con == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ bcopy(&ep->bdaddr, &con->bdaddr, sizeof(con->bdaddr));
+
+ /*
+ * Create HCI command
+ */
+
+ MGETHDR(m, M_NOWAIT, MT_DATA);
+ if (m == NULL) {
+ ng_hci_free_con(con);
+ error = ENOBUFS;
+ goto out;
+ }
+
+ m->m_pkthdr.len = m->m_len = sizeof(*req);
+ req = mtod(m, struct acl_con_req *);
+ req->hdr.type = NG_HCI_CMD_PKT;
+ req->hdr.length = sizeof(req->cp);
+ req->hdr.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LE,
+ NG_HCI_OCF_LE_CREATE_CONNECTION));
+
+ bcopy(&ep->bdaddr, &req->cp.peer_addr, sizeof(req->cp.peer_addr));
+ req->cp.own_address_type = 0;
+ req->cp.peer_addr_type = (link_type == NG_HCI_LINK_LE_RANDOM)? 1:0;
+ req->cp.scan_interval = htole16(4);
+ req->cp.scan_window = htole16(4);
+ req->cp.filter_policy = 0;
+ req->cp.conn_interval_min = htole16(0xf);
+ req->cp.conn_interval_max = htole16(0xf);
+ req->cp.conn_latency = htole16(0);
+ req->cp.supervision_timeout = htole16(0xc80);
+ req->cp.min_ce_length = htole16(1);
+ req->cp.max_ce_length = htole16(1);
+ /*
+ * Adust connection state
+ */
+
+ if (hook != unit->sco)
+ con->flags |= NG_HCI_CON_NOTIFY_ACL;
+ else
+ con->flags |= NG_HCI_CON_NOTIFY_SCO;
+
+ con->state = NG_HCI_CON_W4_CONN_COMPLETE;
+ ng_hci_con_timeout(con);
+
+ /*
+ * Queue and send HCI command
+ */
+
+ NG_BT_MBUFQ_ENQUEUE(&unit->cmdq, m);
+ if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
+ error = ng_hci_send_command(unit);
+out:
+ if (item != NULL)
+ NG_FREE_ITEM(item);
+
+ return (error);
+} /* ng_hci_lp_acl_con_req */
+
/*
* Process LP_DisconnectReq event from the upper layer protocol
*/
@@ -578,7 +764,7 @@ ng_hci_lp_con_cfm(ng_hci_unit_con_p con,
* only SCO upstream hook will receive notification
*/
- if (con->link_type == NG_HCI_LINK_ACL &&
+ if (con->link_type != NG_HCI_LINK_SCO &&
con->flags & NG_HCI_CON_NOTIFY_ACL) {
if (unit->acl != NULL && NG_HOOK_IS_VALID(unit->acl)) {
NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_CON_CFM,
@@ -646,7 +832,7 @@ ng_hci_lp_con_ind(ng_hci_unit_con_p con,
* Use link_type to select upstream hook.
*/
- if (con->link_type == NG_HCI_LINK_ACL)
+ if (con->link_type != NG_HCI_LINK_SCO)
hook = unit->acl;
else
hook = unit->sco;
@@ -887,7 +1073,7 @@ ng_hci_lp_discon_ind(ng_hci_unit_con_p c
* only SCO upstream hook will receive notification.
*/
- if (con->link_type == NG_HCI_LINK_ACL) {
+ if (con->link_type != NG_HCI_LINK_SCO) {
if (unit->acl != NULL && NG_HOOK_IS_VALID(unit->acl)) {
NG_MKMESSAGE(msg, NGM_HCI_COOKIE,
NGM_HCI_LP_DISCON_IND, sizeof(*ep), M_NOWAIT);
Modified: head/sys/netgraph/bluetooth/hci/ng_hci_var.h
==============================================================================
--- head/sys/netgraph/bluetooth/hci/ng_hci_var.h Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/hci/ng_hci_var.h Tue Apr 7 10:22:56 2015 (r281198)
@@ -205,6 +205,7 @@ typedef struct ng_hci_neighbor {
bdaddr_t bdaddr; /* address */
u_int8_t features[NG_HCI_FEATURES_SIZE];
/* LMP features */
+ u_int8_t addrtype; /*Address Type*/
u_int8_t page_scan_rep_mode; /* PS rep. mode */
u_int8_t page_scan_mode; /* page scan mode */
Modified: head/sys/netgraph/bluetooth/include/ng_btsocket.h
==============================================================================
--- head/sys/netgraph/bluetooth/include/ng_btsocket.h Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/include/ng_btsocket.h Tue Apr 7 10:22:56 2015 (r281198)
@@ -221,13 +221,32 @@ struct sockaddr_sco {
* Bluetooth version of struct sockaddr for L2CAP sockets (RAW and SEQPACKET)
*/
+struct sockaddr_l2cap_compat {
+ u_char l2cap_len; /* total length */
+ u_char l2cap_family; /* address family */
+ u_int16_t l2cap_psm; /* PSM (Protocol/Service Multiplexor) */
+ bdaddr_t l2cap_bdaddr; /* address */
+};
+
+#define BDADDR_BREDR 0
+#define BDADDR_LE_PUBLIC 1
+#define BDADDR_LE_RANDOM 2
+
struct sockaddr_l2cap {
u_char l2cap_len; /* total length */
u_char l2cap_family; /* address family */
u_int16_t l2cap_psm; /* PSM (Protocol/Service Multiplexor) */
bdaddr_t l2cap_bdaddr; /* address */
+ u_int16_t l2cap_cid; /*cid*/
+ u_int8_t l2cap_bdaddr_type; /*address type*/
};
+
+#if !defined(L2CAP_SOCKET_CHECKED) && !defined(_KERNEL)
+#warning "Make sure new member of socket address initialized"
+#endif
+
+
/* L2CAP socket options */
#define SOL_L2CAP 0x1609 /* socket option level */
Modified: head/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
==============================================================================
--- head/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h Tue Apr 7 10:22:56 2015 (r281198)
@@ -70,6 +70,8 @@ struct ng_btsocket_l2cap_raw_pcb {
bdaddr_t src; /* source address */
bdaddr_t dst; /* dest address */
+ uint8_t srctype;/*source addr type*/
+ uint8_t dsttype;/*source addr type*/
ng_btsocket_l2cap_rtentry_p rt; /* routing info */
u_int32_t token; /* message token */
@@ -129,6 +131,8 @@ struct ng_btsocket_l2cap_pcb {
bdaddr_t src; /* Source address */
bdaddr_t dst; /* Destination address */
+ uint8_t srctype; /*source addr type*/
+ uint8_t dsttype; /*source addr type*/
u_int16_t psm; /* PSM */
u_int16_t cid; /* Local channel ID */
Modified: head/sys/netgraph/bluetooth/include/ng_hci.h
==============================================================================
--- head/sys/netgraph/bluetooth/include/ng_hci.h Tue Apr 7 09:52:14 2015 (r281197)
+++ head/sys/netgraph/bluetooth/include/ng_hci.h Tue Apr 7 10:22:56 2015 (r281198)
@@ -75,10 +75,11 @@
#define NG_HCI_KEY_SIZE 16 /* link key */
#define NG_HCI_PIN_SIZE 16 /* link PIN */
#define NG_HCI_EVENT_MASK_SIZE 8 /* event mask */
+#define NG_HCI_LE_EVENT_MASK_SIZE 8 /* event mask */
#define NG_HCI_CLASS_SIZE 3 /* unit class */
#define NG_HCI_FEATURES_SIZE 8 /* LMP features */
#define NG_HCI_UNIT_NAME_SIZE 248 /* unit name size */
-
+#define NG_HCI_COMMANDS_SIZE 64 /*Command list BMP size*/
/* HCI specification */
#define NG_HCI_SPEC_V10 0x00 /* v1.0 */
#define NG_HCI_SPEC_V11 0x01 /* v1.1 */
@@ -115,6 +116,8 @@
/* Link types */
#define NG_HCI_LINK_SCO 0x00 /* Voice */
#define NG_HCI_LINK_ACL 0x01 /* Data */
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list