Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
This commit is contained in:
		
						commit
						d2ff5ee919
					
				| @ -96,6 +96,7 @@ static struct usb_device_id btusb_table[] = { | ||||
| 	{ USB_DEVICE(0x0c10, 0x0000) }, | ||||
| 
 | ||||
| 	/* Broadcom BCM20702A0 */ | ||||
| 	{ USB_DEVICE(0x0b05, 0x17b5) }, | ||||
| 	{ USB_DEVICE(0x04ca, 0x2003) }, | ||||
| 	{ USB_DEVICE(0x0489, 0xe042) }, | ||||
| 	{ USB_DEVICE(0x413c, 0x8197) }, | ||||
|  | ||||
| @ -154,7 +154,7 @@ enum { | ||||
| #define HCI_DISCONN_TIMEOUT	msecs_to_jiffies(2000)	/* 2 seconds */ | ||||
| #define HCI_PAIRING_TIMEOUT	msecs_to_jiffies(60000)	/* 60 seconds */ | ||||
| #define HCI_INIT_TIMEOUT	msecs_to_jiffies(10000)	/* 10 seconds */ | ||||
| #define HCI_CMD_TIMEOUT		msecs_to_jiffies(1000)	/* 1 second */ | ||||
| #define HCI_CMD_TIMEOUT		msecs_to_jiffies(2000)	/* 2 seconds */ | ||||
| #define HCI_ACL_TX_TIMEOUT	msecs_to_jiffies(45000)	/* 45 seconds */ | ||||
| #define HCI_AUTO_OFF_TIMEOUT	msecs_to_jiffies(2000)	/* 2 seconds */ | ||||
| 
 | ||||
| @ -319,6 +319,9 @@ enum { | ||||
| #define HCI_FLOW_CTL_MODE_PACKET_BASED	0x00 | ||||
| #define HCI_FLOW_CTL_MODE_BLOCK_BASED	0x01 | ||||
| 
 | ||||
| /* The core spec defines 127 as the "not available" value */ | ||||
| #define HCI_TX_POWER_INVALID	127 | ||||
| 
 | ||||
| /* Extended Inquiry Response field types */ | ||||
| #define EIR_FLAGS		0x01 /* flags */ | ||||
| #define EIR_UUID16_SOME		0x02 /* 16-bit UUID, more available */ | ||||
| @ -335,6 +338,13 @@ enum { | ||||
| #define EIR_SSP_RAND_R		0x0F /* Simple Pairing Randomizer R */ | ||||
| #define EIR_DEVICE_ID		0x10 /* device ID */ | ||||
| 
 | ||||
| /* Low Energy Advertising Flags */ | ||||
| #define LE_AD_LIMITED		0x01 /* Limited Discoverable */ | ||||
| #define LE_AD_GENERAL		0x02 /* General Discoverable */ | ||||
| #define LE_AD_NO_BREDR		0x04 /* BR/EDR not supported */ | ||||
| #define LE_AD_SIM_LE_BREDR_CTRL	0x08 /* Simultaneous LE & BR/EDR Controller */ | ||||
| #define LE_AD_SIM_LE_BREDR_HOST	0x10 /* Simultaneous LE & BR/EDR Host */ | ||||
| 
 | ||||
| /* -----  HCI Commands ---- */ | ||||
| #define HCI_OP_NOP			0x0000 | ||||
| 
 | ||||
| @ -939,6 +949,16 @@ struct hci_rp_le_read_adv_tx_power { | ||||
| 	__s8	tx_power; | ||||
| } __packed; | ||||
| 
 | ||||
| #define HCI_MAX_AD_LENGTH		31 | ||||
| 
 | ||||
| #define HCI_OP_LE_SET_ADV_DATA		0x2008 | ||||
| struct hci_cp_le_set_adv_data { | ||||
| 	__u8	length; | ||||
| 	__u8	data[HCI_MAX_AD_LENGTH]; | ||||
| } __packed; | ||||
| 
 | ||||
| #define HCI_OP_LE_SET_ADV_ENABLE	0x200a | ||||
| 
 | ||||
| #define HCI_OP_LE_SET_SCAN_PARAM	0x200b | ||||
| struct hci_cp_le_set_scan_param { | ||||
| 	__u8    type; | ||||
|  | ||||
| @ -279,6 +279,8 @@ struct hci_dev { | ||||
| 	struct le_scan_params	le_scan_params; | ||||
| 
 | ||||
| 	__s8			adv_tx_power; | ||||
| 	__u8			adv_data[HCI_MAX_AD_LENGTH]; | ||||
| 	__u8			adv_data_len; | ||||
| 
 | ||||
| 	int (*open)(struct hci_dev *hdev); | ||||
| 	int (*close)(struct hci_dev *hdev); | ||||
| @ -734,6 +736,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | ||||
| 								u8 *randomizer); | ||||
| int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); | ||||
| 
 | ||||
| int hci_update_ad(struct hci_dev *hdev); | ||||
| 
 | ||||
| void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); | ||||
| 
 | ||||
| int hci_recv_frame(struct sk_buff *skb); | ||||
|  | ||||
| @ -811,6 +811,6 @@ void l2cap_send_conn_req(struct l2cap_chan *chan); | ||||
| void l2cap_move_start(struct l2cap_chan *chan); | ||||
| void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, | ||||
| 		       u8 status); | ||||
| void l2cap_physical_cfm(struct l2cap_chan *chan, int result); | ||||
| void __l2cap_physical_cfm(struct l2cap_chan *chan, int result); | ||||
| 
 | ||||
| #endif /* __L2CAP_H */ | ||||
|  | ||||
| @ -386,13 +386,17 @@ void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon) | ||||
| 
 | ||||
| 	bredr_chan = mgr->bredr_chan; | ||||
| 
 | ||||
| 	l2cap_chan_lock(bredr_chan); | ||||
| 
 | ||||
| 	set_bit(FLAG_EFS_ENABLE, &bredr_chan->flags); | ||||
| 	bredr_chan->remote_amp_id = hs_hcon->remote_id; | ||||
| 	bredr_chan->local_amp_id = hs_hcon->hdev->id; | ||||
| 	bredr_chan->hs_hcon = hs_hcon; | ||||
| 	bredr_chan->conn->mtu = hs_hcon->hdev->block_mtu; | ||||
| 	bredr_chan->fcs = L2CAP_FCS_NONE; | ||||
| 
 | ||||
| 	l2cap_physical_cfm(bredr_chan, 0); | ||||
| 	__l2cap_physical_cfm(bredr_chan, 0); | ||||
| 
 | ||||
| 	l2cap_chan_unlock(bredr_chan); | ||||
| 
 | ||||
| 	hci_dev_put(bredr_hdev); | ||||
| } | ||||
|  | ||||
| @ -434,6 +434,8 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, | ||||
| 
 | ||||
| 	BT_DBG("cache %p, %pMR", cache, &data->bdaddr); | ||||
| 
 | ||||
| 	hci_remove_remote_oob_data(hdev, &data->bdaddr); | ||||
| 
 | ||||
| 	if (ssp) | ||||
| 		*ssp = data->ssp_mode; | ||||
| 
 | ||||
| @ -594,6 +596,99 @@ done: | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| static u8 create_ad(struct hci_dev *hdev, u8 *ptr) | ||||
| { | ||||
| 	u8 ad_len = 0, flags = 0; | ||||
| 	size_t name_len; | ||||
| 
 | ||||
| 	if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) | ||||
| 		flags |= LE_AD_GENERAL; | ||||
| 
 | ||||
| 	if (!lmp_bredr_capable(hdev)) | ||||
| 		flags |= LE_AD_NO_BREDR; | ||||
| 
 | ||||
| 	if (lmp_le_br_capable(hdev)) | ||||
| 		flags |= LE_AD_SIM_LE_BREDR_CTRL; | ||||
| 
 | ||||
| 	if (lmp_host_le_br_capable(hdev)) | ||||
| 		flags |= LE_AD_SIM_LE_BREDR_HOST; | ||||
| 
 | ||||
| 	if (flags) { | ||||
| 		BT_DBG("adv flags 0x%02x", flags); | ||||
| 
 | ||||
| 		ptr[0] = 2; | ||||
| 		ptr[1] = EIR_FLAGS; | ||||
| 		ptr[2] = flags; | ||||
| 
 | ||||
| 		ad_len += 3; | ||||
| 		ptr += 3; | ||||
| 	} | ||||
| 
 | ||||
| 	if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) { | ||||
| 		ptr[0] = 2; | ||||
| 		ptr[1] = EIR_TX_POWER; | ||||
| 		ptr[2] = (u8) hdev->adv_tx_power; | ||||
| 
 | ||||
| 		ad_len += 3; | ||||
| 		ptr += 3; | ||||
| 	} | ||||
| 
 | ||||
| 	name_len = strlen(hdev->dev_name); | ||||
| 	if (name_len > 0) { | ||||
| 		size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2; | ||||
| 
 | ||||
| 		if (name_len > max_len) { | ||||
| 			name_len = max_len; | ||||
| 			ptr[1] = EIR_NAME_SHORT; | ||||
| 		} else | ||||
| 			ptr[1] = EIR_NAME_COMPLETE; | ||||
| 
 | ||||
| 		ptr[0] = name_len + 1; | ||||
| 
 | ||||
| 		memcpy(ptr + 2, hdev->dev_name, name_len); | ||||
| 
 | ||||
| 		ad_len += (name_len + 2); | ||||
| 		ptr += (name_len + 2); | ||||
| 	} | ||||
| 
 | ||||
| 	return ad_len; | ||||
| } | ||||
| 
 | ||||
| int hci_update_ad(struct hci_dev *hdev) | ||||
| { | ||||
| 	struct hci_cp_le_set_adv_data cp; | ||||
| 	u8 len; | ||||
| 	int err; | ||||
| 
 | ||||
| 	hci_dev_lock(hdev); | ||||
| 
 | ||||
| 	if (!lmp_le_capable(hdev)) { | ||||
| 		err = -EINVAL; | ||||
| 		goto unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	memset(&cp, 0, sizeof(cp)); | ||||
| 
 | ||||
| 	len = create_ad(hdev, cp.data); | ||||
| 
 | ||||
| 	if (hdev->adv_data_len == len && | ||||
| 	    memcmp(cp.data, hdev->adv_data, len) == 0) { | ||||
| 		err = 0; | ||||
| 		goto unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); | ||||
| 	hdev->adv_data_len = len; | ||||
| 
 | ||||
| 	cp.length = len; | ||||
| 	err = hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | ||||
| 
 | ||||
| unlock: | ||||
| 	hci_dev_unlock(hdev); | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| /* ---- HCI ioctl helpers ---- */ | ||||
| 
 | ||||
| int hci_dev_open(__u16 dev) | ||||
| @ -651,6 +746,7 @@ int hci_dev_open(__u16 dev) | ||||
| 		hci_dev_hold(hdev); | ||||
| 		set_bit(HCI_UP, &hdev->flags); | ||||
| 		hci_notify(hdev, HCI_DEV_UP); | ||||
| 		hci_update_ad(hdev); | ||||
| 		if (!test_bit(HCI_SETUP, &hdev->dev_flags) && | ||||
| 		    mgmt_valid_hdev(hdev)) { | ||||
| 			hci_dev_lock(hdev); | ||||
| @ -1606,6 +1702,8 @@ struct hci_dev *hci_alloc_dev(void) | ||||
| 	hdev->esco_type = (ESCO_HV1); | ||||
| 	hdev->link_mode = (HCI_LM_ACCEPT); | ||||
| 	hdev->io_capability = 0x03; /* No Input No Output */ | ||||
| 	hdev->inq_tx_power = HCI_TX_POWER_INVALID; | ||||
| 	hdev->adv_tx_power = HCI_TX_POWER_INVALID; | ||||
| 
 | ||||
| 	hdev->sniff_max_interval = 800; | ||||
| 	hdev->sniff_min_interval = 80; | ||||
|  | ||||
| @ -202,6 +202,11 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | ||||
| 			     BIT(HCI_PERIODIC_INQ)); | ||||
| 
 | ||||
| 	hdev->discovery.state = DISCOVERY_STOPPED; | ||||
| 	hdev->inq_tx_power = HCI_TX_POWER_INVALID; | ||||
| 	hdev->adv_tx_power = HCI_TX_POWER_INVALID; | ||||
| 
 | ||||
| 	memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); | ||||
| 	hdev->adv_data_len = 0; | ||||
| } | ||||
| 
 | ||||
| static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | ||||
| @ -224,6 +229,9 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) | ||||
| 
 | ||||
| 	hci_dev_unlock(hdev); | ||||
| 
 | ||||
| 	if (!status && !test_bit(HCI_INIT, &hdev->flags)) | ||||
| 		hci_update_ad(hdev); | ||||
| 
 | ||||
| 	hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); | ||||
| } | ||||
| 
 | ||||
| @ -1089,8 +1097,11 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | ||||
| 
 | ||||
| 	BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||||
| 
 | ||||
| 	if (!rp->status) | ||||
| 	if (!rp->status) { | ||||
| 		hdev->adv_tx_power = rp->tx_power; | ||||
| 		if (!test_bit(HCI_INIT, &hdev->flags)) | ||||
| 			hci_update_ad(hdev); | ||||
| 	} | ||||
| 
 | ||||
| 	hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); | ||||
| } | ||||
| @ -1179,6 +1190,33 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | ||||
| 	hci_dev_unlock(hdev); | ||||
| } | ||||
| 
 | ||||
| static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | ||||
| { | ||||
| 	__u8 *sent, status = *((__u8 *) skb->data); | ||||
| 
 | ||||
| 	BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||||
| 
 | ||||
| 	sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); | ||||
| 	if (!sent) | ||||
| 		return; | ||||
| 
 | ||||
| 	hci_dev_lock(hdev); | ||||
| 
 | ||||
| 	if (!status) { | ||||
| 		if (*sent) | ||||
| 			set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | ||||
| 		else | ||||
| 			clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); | ||||
| 	} | ||||
| 
 | ||||
| 	hci_dev_unlock(hdev); | ||||
| 
 | ||||
| 	if (!test_bit(HCI_INIT, &hdev->flags)) | ||||
| 		hci_update_ad(hdev); | ||||
| 
 | ||||
| 	hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status); | ||||
| } | ||||
| 
 | ||||
| static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | ||||
| { | ||||
| 	__u8 status = *((__u8 *) skb->data); | ||||
| @ -2574,6 +2612,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||||
| 		hci_cc_le_set_scan_param(hdev, skb); | ||||
| 		break; | ||||
| 
 | ||||
| 	case HCI_OP_LE_SET_ADV_ENABLE: | ||||
| 		hci_cc_le_set_adv_enable(hdev, skb); | ||||
| 		break; | ||||
| 
 | ||||
| 	case HCI_OP_LE_SET_SCAN_ENABLE: | ||||
| 		hci_cc_le_set_scan_enable(hdev, skb); | ||||
| 		break; | ||||
|  | ||||
| @ -4284,9 +4284,9 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, | ||||
| 
 | ||||
| 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); | ||||
| 
 | ||||
| 		chan->local_amp_id = req->amp_id; | ||||
| 		mgr->bredr_chan = chan; | ||||
| 		chan->hs_hcon = hs_hcon; | ||||
| 		chan->fcs = L2CAP_FCS_NONE; | ||||
| 		conn->mtu = hdev->block_mtu; | ||||
| 	} | ||||
| 
 | ||||
| @ -4518,21 +4518,39 @@ void l2cap_move_start(struct l2cap_chan *chan) | ||||
| static void l2cap_do_create(struct l2cap_chan *chan, int result, | ||||
| 			    u8 local_amp_id, u8 remote_amp_id) | ||||
| { | ||||
| 	if (!test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { | ||||
| 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state), | ||||
| 	       local_amp_id, remote_amp_id); | ||||
| 
 | ||||
| 	chan->fcs = L2CAP_FCS_NONE; | ||||
| 
 | ||||
| 	/* Outgoing channel on AMP */ | ||||
| 	if (chan->state == BT_CONNECT) { | ||||
| 		if (result == L2CAP_CR_SUCCESS) { | ||||
| 			chan->local_amp_id = local_amp_id; | ||||
| 			l2cap_send_create_chan_req(chan, remote_amp_id); | ||||
| 		} else { | ||||
| 			/* Revert to BR/EDR connect */ | ||||
| 			l2cap_send_conn_req(chan); | ||||
| 		} | ||||
| 
 | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Incoming channel on AMP */ | ||||
| 	if (__l2cap_no_conn_pending(chan)) { | ||||
| 		struct l2cap_conn_rsp rsp; | ||||
| 		char buf[128]; | ||||
| 		rsp.scid = cpu_to_le16(chan->dcid); | ||||
| 		rsp.dcid = cpu_to_le16(chan->scid); | ||||
| 
 | ||||
| 		/* Incoming channel on AMP */ | ||||
| 		if (result == L2CAP_CR_SUCCESS) { | ||||
| 			/* Send successful response */ | ||||
| 			rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); | ||||
| 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); | ||||
| 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | ||||
| 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | ||||
| 		} else { | ||||
| 			/* Send negative response */ | ||||
| 			rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM); | ||||
| 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); | ||||
| 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); | ||||
| 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | ||||
| 		} | ||||
| 
 | ||||
| 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, | ||||
| @ -4546,15 +4564,6 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result, | ||||
| 				       l2cap_build_conf_req(chan, buf), buf); | ||||
| 			chan->num_conf_req++; | ||||
| 		} | ||||
| 	} else { | ||||
| 		/* Outgoing channel on AMP */ | ||||
| 		if (result == L2CAP_CR_SUCCESS) { | ||||
| 			chan->local_amp_id = local_amp_id; | ||||
| 			l2cap_send_create_chan_req(chan, remote_amp_id); | ||||
| 		} else { | ||||
| 			/* Revert to BR/EDR connect */ | ||||
| 			l2cap_send_conn_req(chan); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -4612,7 +4621,8 @@ static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result) | ||||
| 	l2cap_ertm_send(chan); | ||||
| } | ||||
| 
 | ||||
| void l2cap_physical_cfm(struct l2cap_chan *chan, int result) | ||||
| /* Invoke with locked chan */ | ||||
| void __l2cap_physical_cfm(struct l2cap_chan *chan, int result) | ||||
| { | ||||
| 	u8 local_amp_id = chan->local_amp_id; | ||||
| 	u8 remote_amp_id = chan->remote_amp_id; | ||||
| @ -4620,8 +4630,6 @@ void l2cap_physical_cfm(struct l2cap_chan *chan, int result) | ||||
| 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d", | ||||
| 	       chan, result, local_amp_id, remote_amp_id); | ||||
| 
 | ||||
| 	l2cap_chan_lock(chan); | ||||
| 
 | ||||
| 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) { | ||||
| 		l2cap_chan_unlock(chan); | ||||
| 		return; | ||||
| @ -4645,8 +4653,6 @@ void l2cap_physical_cfm(struct l2cap_chan *chan, int result) | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	l2cap_chan_unlock(chan); | ||||
| } | ||||
| 
 | ||||
| static inline int l2cap_move_channel_req(struct l2cap_conn *conn, | ||||
| @ -6086,7 +6092,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | ||||
| 		       control->super); | ||||
| 
 | ||||
| 		if (len != 0) { | ||||
| 			BT_ERR("%d", len); | ||||
| 			BT_ERR("Trailing bytes: %d in sframe", len); | ||||
| 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||||
| 			goto drop; | ||||
| 		} | ||||
| @ -6380,7 +6386,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) { | ||||
| 		if (!__l2cap_no_conn_pending(chan)) { | ||||
| 			l2cap_chan_unlock(chan); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| @ -485,7 +485,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data) | ||||
| 		ptr += (name_len + 2); | ||||
| 	} | ||||
| 
 | ||||
| 	if (hdev->inq_tx_power) { | ||||
| 	if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) { | ||||
| 		ptr[0] = 2; | ||||
| 		ptr[1] = EIR_TX_POWER; | ||||
| 		ptr[2] = (u8) hdev->inq_tx_power; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user