Bluetooth: Add support for Read Unconfigured Index List command
This command allows to get the list of currently known controller that are in unconfigured state. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
		
					parent
					
						
							
								edd3896bc4
							
						
					
				
			
			
				commit
				
					
						73d1df2a7a
					
				
			
		
					 2 changed files with 88 additions and 10 deletions
				
			
		| 
						 | 
					@ -464,6 +464,13 @@ struct mgmt_cp_load_conn_param {
 | 
				
			||||||
} __packed;
 | 
					} __packed;
 | 
				
			||||||
#define MGMT_LOAD_CONN_PARAM_SIZE	2
 | 
					#define MGMT_LOAD_CONN_PARAM_SIZE	2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MGMT_OP_READ_UNCONF_INDEX_LIST	0x0036
 | 
				
			||||||
 | 
					#define MGMT_READ_UNCONF_INDEX_LIST_SIZE 0
 | 
				
			||||||
 | 
					struct mgmt_rp_read_unconf_index_list {
 | 
				
			||||||
 | 
						__le16	num_controllers;
 | 
				
			||||||
 | 
						__le16	index[0];
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MGMT_EV_CMD_COMPLETE		0x0001
 | 
					#define MGMT_EV_CMD_COMPLETE		0x0001
 | 
				
			||||||
struct mgmt_ev_cmd_complete {
 | 
					struct mgmt_ev_cmd_complete {
 | 
				
			||||||
	__le16	opcode;
 | 
						__le16	opcode;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,6 +89,7 @@ static const u16 mgmt_commands[] = {
 | 
				
			||||||
	MGMT_OP_ADD_DEVICE,
 | 
						MGMT_OP_ADD_DEVICE,
 | 
				
			||||||
	MGMT_OP_REMOVE_DEVICE,
 | 
						MGMT_OP_REMOVE_DEVICE,
 | 
				
			||||||
	MGMT_OP_LOAD_CONN_PARAM,
 | 
						MGMT_OP_LOAD_CONN_PARAM,
 | 
				
			||||||
 | 
						MGMT_OP_READ_UNCONF_INDEX_LIST,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const u16 mgmt_events[] = {
 | 
					static const u16 mgmt_events[] = {
 | 
				
			||||||
| 
						 | 
					@ -336,7 +337,8 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	count = 0;
 | 
						count = 0;
 | 
				
			||||||
	list_for_each_entry(d, &hci_dev_list, list) {
 | 
						list_for_each_entry(d, &hci_dev_list, list) {
 | 
				
			||||||
		if (d->dev_type == HCI_BREDR)
 | 
							if (d->dev_type == HCI_BREDR &&
 | 
				
			||||||
 | 
							    !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
 | 
				
			||||||
			count++;
 | 
								count++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -349,16 +351,18 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	count = 0;
 | 
						count = 0;
 | 
				
			||||||
	list_for_each_entry(d, &hci_dev_list, list) {
 | 
						list_for_each_entry(d, &hci_dev_list, list) {
 | 
				
			||||||
		if (test_bit(HCI_SETUP, &d->dev_flags))
 | 
							if (test_bit(HCI_SETUP, &d->dev_flags) ||
 | 
				
			||||||
 | 
							    test_bit(HCI_USER_CHANNEL, &d->dev_flags))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
 | 
							/* Devices marked as raw-only are neither configured
 | 
				
			||||||
 | 
							 * nor unconfigured controllers.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (test_bit(HCI_UNCONFIGURED, &d->dev_flags))
 | 
							if (d->dev_type == HCI_BREDR &&
 | 
				
			||||||
			continue;
 | 
							    !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (d->dev_type == HCI_BREDR) {
 | 
					 | 
				
			||||||
			rp->index[count++] = cpu_to_le16(d->id);
 | 
								rp->index[count++] = cpu_to_le16(d->id);
 | 
				
			||||||
			BT_DBG("Added hci%u", d->id);
 | 
								BT_DBG("Added hci%u", d->id);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -377,6 +381,65 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
 | 
				
			||||||
 | 
									  void *data, u16 data_len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mgmt_rp_read_unconf_index_list *rp;
 | 
				
			||||||
 | 
						struct hci_dev *d;
 | 
				
			||||||
 | 
						size_t rp_len;
 | 
				
			||||||
 | 
						u16 count;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BT_DBG("sock %p", sk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						read_lock(&hci_dev_list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count = 0;
 | 
				
			||||||
 | 
						list_for_each_entry(d, &hci_dev_list, list) {
 | 
				
			||||||
 | 
							if (d->dev_type == HCI_BREDR &&
 | 
				
			||||||
 | 
							    test_bit(HCI_UNCONFIGURED, &d->dev_flags))
 | 
				
			||||||
 | 
								count++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rp_len = sizeof(*rp) + (2 * count);
 | 
				
			||||||
 | 
						rp = kmalloc(rp_len, GFP_ATOMIC);
 | 
				
			||||||
 | 
						if (!rp) {
 | 
				
			||||||
 | 
							read_unlock(&hci_dev_list_lock);
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						count = 0;
 | 
				
			||||||
 | 
						list_for_each_entry(d, &hci_dev_list, list) {
 | 
				
			||||||
 | 
							if (test_bit(HCI_SETUP, &d->dev_flags) ||
 | 
				
			||||||
 | 
							    test_bit(HCI_USER_CHANNEL, &d->dev_flags))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Devices marked as raw-only are neither configured
 | 
				
			||||||
 | 
							 * nor unconfigured controllers.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (d->dev_type == HCI_BREDR &&
 | 
				
			||||||
 | 
							    test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
 | 
				
			||||||
 | 
								rp->index[count++] = cpu_to_le16(d->id);
 | 
				
			||||||
 | 
								BT_DBG("Added hci%u", d->id);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rp->num_controllers = cpu_to_le16(count);
 | 
				
			||||||
 | 
						rp_len = sizeof(*rp) + (2 * count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						read_unlock(&hci_dev_list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
 | 
				
			||||||
 | 
								   0, rp, rp_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kfree(rp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u32 get_supported_settings(struct hci_dev *hdev)
 | 
					static u32 get_supported_settings(struct hci_dev *hdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 settings = 0;
 | 
						u32 settings = 0;
 | 
				
			||||||
| 
						 | 
					@ -5274,6 +5337,7 @@ static const struct mgmt_handler {
 | 
				
			||||||
	{ add_device,             false, MGMT_ADD_DEVICE_SIZE },
 | 
						{ add_device,             false, MGMT_ADD_DEVICE_SIZE },
 | 
				
			||||||
	{ remove_device,          false, MGMT_REMOVE_DEVICE_SIZE },
 | 
						{ remove_device,          false, MGMT_REMOVE_DEVICE_SIZE },
 | 
				
			||||||
	{ load_conn_param,        true,  MGMT_LOAD_CONN_PARAM_SIZE },
 | 
						{ load_conn_param,        true,  MGMT_LOAD_CONN_PARAM_SIZE },
 | 
				
			||||||
 | 
						{ read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 | 
					int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 | 
				
			||||||
| 
						 | 
					@ -5335,8 +5399,15 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 | 
				
			||||||
		goto done;
 | 
							goto done;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((hdev && opcode < MGMT_OP_READ_INFO) ||
 | 
						if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
 | 
				
			||||||
	    (!hdev && opcode >= MGMT_OP_READ_INFO)) {
 | 
							     opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
 | 
				
			||||||
 | 
							err = cmd_status(sk, index, opcode,
 | 
				
			||||||
 | 
									 MGMT_STATUS_INVALID_INDEX);
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
 | 
				
			||||||
 | 
							      opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
 | 
				
			||||||
		err = cmd_status(sk, index, opcode,
 | 
							err = cmd_status(sk, index, opcode,
 | 
				
			||||||
				 MGMT_STATUS_INVALID_INDEX);
 | 
									 MGMT_STATUS_INVALID_INDEX);
 | 
				
			||||||
		goto done;
 | 
							goto done;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue