mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	Bluetooth: hci_sync: Convert MGMT_OP_GET_CLOCK_INFO
Synchronous version of MGMT_OP_GET_CLOCK_INFO. Signed-off-by: Brian Gix <brian.gix@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
		
							parent
							
								
									2f2eb0c9de
								
							
						
					
					
						commit
						5a75013746
					
				
					 3 changed files with 62 additions and 74 deletions
				
			
		| 
						 | 
					@ -70,6 +70,7 @@ int hci_update_passive_scan(struct hci_dev *hdev);
 | 
				
			||||||
int hci_read_rssi_sync(struct hci_dev *hdev, __le16 handle);
 | 
					int hci_read_rssi_sync(struct hci_dev *hdev, __le16 handle);
 | 
				
			||||||
int hci_read_tx_power_sync(struct hci_dev *hdev, __le16 handle, u8 type);
 | 
					int hci_read_tx_power_sync(struct hci_dev *hdev, __le16 handle, u8 type);
 | 
				
			||||||
int hci_write_sc_support_sync(struct hci_dev *hdev, u8 val);
 | 
					int hci_write_sc_support_sync(struct hci_dev *hdev, u8 val);
 | 
				
			||||||
 | 
					int hci_read_clock_sync(struct hci_dev *hdev, struct hci_cp_read_clock *cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int hci_write_fast_connectable_sync(struct hci_dev *hdev, bool enable);
 | 
					int hci_write_fast_connectable_sync(struct hci_dev *hdev, bool enable);
 | 
				
			||||||
int hci_update_scan_sync(struct hci_dev *hdev);
 | 
					int hci_update_scan_sync(struct hci_dev *hdev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1318,6 +1318,12 @@ int hci_read_rssi_sync(struct hci_dev *hdev, __le16 handle)
 | 
				
			||||||
					sizeof(cp), &cp, HCI_CMD_TIMEOUT);
 | 
										sizeof(cp), &cp, HCI_CMD_TIMEOUT);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int hci_read_clock_sync(struct hci_dev *hdev, struct hci_cp_read_clock *cp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return __hci_cmd_sync_status(hdev, HCI_OP_READ_CLOCK,
 | 
				
			||||||
 | 
										sizeof(*cp), cp, HCI_CMD_TIMEOUT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int hci_read_tx_power_sync(struct hci_dev *hdev, __le16 handle, u8 type)
 | 
					int hci_read_tx_power_sync(struct hci_dev *hdev, __le16 handle, u8 type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hci_cp_read_tx_power cp;
 | 
						struct hci_cp_read_tx_power cp;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -927,13 +927,6 @@ static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
 | 
				
			||||||
	return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
 | 
						return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct mgmt_pending_cmd *pending_find_data(u16 opcode,
 | 
					 | 
				
			||||||
						  struct hci_dev *hdev,
 | 
					 | 
				
			||||||
						  const void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return mgmt_pending_find_data(HCI_CHANNEL_CONTROL, opcode, hdev, data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
u8 mgmt_get_adv_discov_flags(struct hci_dev *hdev)
 | 
					u8 mgmt_get_adv_discov_flags(struct hci_dev *hdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mgmt_pending_cmd *cmd;
 | 
						struct mgmt_pending_cmd *cmd;
 | 
				
			||||||
| 
						 | 
					@ -6702,72 +6695,68 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
 | 
					static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hci_conn *conn = cmd->user_data;
 | 
						struct mgmt_pending_cmd *cmd = data;
 | 
				
			||||||
 | 
						struct mgmt_cp_get_clock_info *cp = cmd->param;
 | 
				
			||||||
	struct mgmt_rp_get_clock_info rp;
 | 
						struct mgmt_rp_get_clock_info rp;
 | 
				
			||||||
	struct hci_dev *hdev;
 | 
						struct hci_conn *conn = cmd->user_data;
 | 
				
			||||||
	int err;
 | 
						u8 status = mgmt_status(err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bt_dev_dbg(hdev, "err %d", err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&rp, 0, sizeof(rp));
 | 
						memset(&rp, 0, sizeof(rp));
 | 
				
			||||||
	memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
 | 
						bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
 | 
				
			||||||
 | 
						rp.addr.type = cp->addr.type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (status)
 | 
						if (err)
 | 
				
			||||||
		goto complete;
 | 
							goto complete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hdev = hci_dev_get(cmd->index);
 | 
					 | 
				
			||||||
	if (hdev) {
 | 
					 | 
				
			||||||
	rp.local_clock = cpu_to_le32(hdev->clock);
 | 
						rp.local_clock = cpu_to_le32(hdev->clock);
 | 
				
			||||||
		hci_dev_put(hdev);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (conn) {
 | 
						if (conn) {
 | 
				
			||||||
		rp.piconet_clock = cpu_to_le32(conn->clock);
 | 
							rp.piconet_clock = cpu_to_le32(conn->clock);
 | 
				
			||||||
		rp.accuracy = cpu_to_le16(conn->clock_accuracy);
 | 
							rp.accuracy = cpu_to_le16(conn->clock_accuracy);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
complete:
 | 
					 | 
				
			||||||
	err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
 | 
					 | 
				
			||||||
				sizeof(rp));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (conn) {
 | 
					 | 
				
			||||||
		hci_conn_drop(conn);
 | 
							hci_conn_drop(conn);
 | 
				
			||||||
		hci_conn_put(conn);
 | 
							hci_conn_put(conn);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return err;
 | 
					complete:
 | 
				
			||||||
 | 
						mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
 | 
				
			||||||
 | 
								  sizeof(rp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mgmt_pending_free(cmd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
 | 
					static int get_clock_info_sync(struct hci_dev *hdev, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hci_cp_read_clock *hci_cp;
 | 
						struct mgmt_pending_cmd *cmd = data;
 | 
				
			||||||
	struct mgmt_pending_cmd *cmd;
 | 
						struct mgmt_cp_get_clock_info *cp = cmd->param;
 | 
				
			||||||
	struct hci_conn *conn;
 | 
						struct hci_cp_read_clock hci_cp;
 | 
				
			||||||
 | 
						struct hci_conn *conn = cmd->user_data;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bt_dev_dbg(hdev, "status %u", status);
 | 
						memset(&hci_cp, 0, sizeof(hci_cp));
 | 
				
			||||||
 | 
						err = hci_read_clock_sync(hdev, &hci_cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hci_dev_lock(hdev);
 | 
						if (conn) {
 | 
				
			||||||
 | 
							/* Make sure connection still exists */
 | 
				
			||||||
 | 
							conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
 | 
				
			||||||
 | 
										       &cp->addr.bdaddr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
 | 
							if (conn && conn == cmd->user_data &&
 | 
				
			||||||
	if (!hci_cp)
 | 
							    conn->state == BT_CONNECTED) {
 | 
				
			||||||
		goto unlock;
 | 
								hci_cp.handle = cpu_to_le16(conn->handle);
 | 
				
			||||||
 | 
								hci_cp.which = 0x01; /* Piconet clock */
 | 
				
			||||||
	if (hci_cp->which) {
 | 
								err = hci_read_clock_sync(hdev, &hci_cp);
 | 
				
			||||||
		u16 handle = __le16_to_cpu(hci_cp->handle);
 | 
							} else if (cmd->user_data) {
 | 
				
			||||||
		conn = hci_conn_hash_lookup_handle(hdev, handle);
 | 
								hci_conn_drop(cmd->user_data);
 | 
				
			||||||
	} else {
 | 
								hci_conn_put(cmd->user_data);
 | 
				
			||||||
		conn = NULL;
 | 
								cmd->user_data = NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd = pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
 | 
						return err;
 | 
				
			||||||
	if (!cmd)
 | 
					 | 
				
			||||||
		goto unlock;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmd->cmd_complete(cmd, mgmt_status(status));
 | 
					 | 
				
			||||||
	mgmt_pending_remove(cmd);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
unlock:
 | 
					 | 
				
			||||||
	hci_dev_unlock(hdev);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
 | 
					static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
 | 
				
			||||||
| 
						 | 
					@ -6775,9 +6764,7 @@ static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mgmt_cp_get_clock_info *cp = data;
 | 
						struct mgmt_cp_get_clock_info *cp = data;
 | 
				
			||||||
	struct mgmt_rp_get_clock_info rp;
 | 
						struct mgmt_rp_get_clock_info rp;
 | 
				
			||||||
	struct hci_cp_read_clock hci_cp;
 | 
					 | 
				
			||||||
	struct mgmt_pending_cmd *cmd;
 | 
						struct mgmt_pending_cmd *cmd;
 | 
				
			||||||
	struct hci_request req;
 | 
					 | 
				
			||||||
	struct hci_conn *conn;
 | 
						struct hci_conn *conn;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6815,31 +6802,25 @@ static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
 | 
				
			||||||
		conn = NULL;
 | 
							conn = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
 | 
						cmd = mgmt_pending_new(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
 | 
				
			||||||
	if (!cmd) {
 | 
						if (!cmd)
 | 
				
			||||||
		err = -ENOMEM;
 | 
							err = -ENOMEM;
 | 
				
			||||||
		goto unlock;
 | 
						else
 | 
				
			||||||
	}
 | 
							err = hci_cmd_sync_queue(hdev, get_clock_info_sync, cmd,
 | 
				
			||||||
 | 
										 get_clock_info_complete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd->cmd_complete = clock_info_cmd_complete;
 | 
						if (err < 0) {
 | 
				
			||||||
 | 
							err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
 | 
				
			||||||
 | 
										MGMT_STATUS_FAILED, &rp, sizeof(rp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hci_req_init(&req, hdev);
 | 
							if (cmd)
 | 
				
			||||||
 | 
								mgmt_pending_free(cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&hci_cp, 0, sizeof(hci_cp));
 | 
						} else if (conn) {
 | 
				
			||||||
	hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (conn) {
 | 
					 | 
				
			||||||
		hci_conn_hold(conn);
 | 
							hci_conn_hold(conn);
 | 
				
			||||||
		cmd->user_data = hci_conn_get(conn);
 | 
							cmd->user_data = hci_conn_get(conn);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		hci_cp.handle = cpu_to_le16(conn->handle);
 | 
					 | 
				
			||||||
		hci_cp.which = 0x01; /* Piconet clock */
 | 
					 | 
				
			||||||
		hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = hci_req_run(&req, get_clock_info_complete);
 | 
					 | 
				
			||||||
	if (err < 0)
 | 
					 | 
				
			||||||
		mgmt_pending_remove(cmd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
unlock:
 | 
					unlock:
 | 
				
			||||||
	hci_dev_unlock(hdev);
 | 
						hci_dev_unlock(hdev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue