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-head mailing list