linux/net/bluetooth/hci_core.c

/*
   BlueZ - Bluetooth protocol stack for Linux
   Copyright (C) 2000-2001 Qualcomm Incorporated
   Copyright (C) 2011 ProFUSION Embedded Systems

   Written 2000,2001 by Maxim Krasnyansky <[email protected]>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 as
   published by the Free Software Foundation;

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
   SOFTWARE IS DISCLAIMED.
*/

/* Bluetooth HCI core. */

#include <linux/export.h>
#include <linux/rfkill.h>
#include <linux/debugfs.h>
#include <linux/crypto.h>
#include <linux/kcov.h>
#include <linux/property.h>
#include <linux/suspend.h>
#include <linux/wait.h>
#include <asm/unaligned.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/mgmt.h>

#include "hci_debugfs.h"
#include "smp.h"
#include "leds.h"
#include "msft.h"
#include "aosp.h"
#include "hci_codec.h"

static void hci_rx_work(struct work_struct *work);
static void hci_cmd_work(struct work_struct *work);
static void hci_tx_work(struct work_struct *work);

/* HCI device list */
LIST_HEAD();
DEFINE_RWLOCK();

/* HCI callback list */
LIST_HEAD();
DEFINE_MUTEX();

/* HCI ID Numbering */
static DEFINE_IDA(hci_index_ida);

/* Get HCI device by index.
 * Device is held on return. */
struct hci_dev *hci_dev_get(int index)
{}

/* ---- Inquiry support ---- */

bool hci_discovery_active(struct hci_dev *hdev)
{}

void hci_discovery_set_state(struct hci_dev *hdev, int state)
{}

void hci_inquiry_cache_flush(struct hci_dev *hdev)
{}

struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
					       bdaddr_t *bdaddr)
{}

struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev,
						       bdaddr_t *bdaddr)
{}

struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev,
						       bdaddr_t *bdaddr,
						       int state)
{}

void hci_inquiry_cache_update_resolve(struct hci_dev *hdev,
				      struct inquiry_entry *ie)
{}

u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
			     bool name_known)
{}

static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf)
{}

int hci_inquiry(void __user *arg)
{}

static int hci_dev_do_open(struct hci_dev *hdev)
{}

/* ---- HCI ioctl helpers ---- */

int hci_dev_open(__u16 dev)
{}

int hci_dev_do_close(struct hci_dev *hdev)
{}

int hci_dev_close(__u16 dev)
{}

static int hci_dev_do_reset(struct hci_dev *hdev)
{}

int hci_dev_reset(__u16 dev)
{}

int hci_dev_reset_stat(__u16 dev)
{}

static void hci_update_passive_scan_state(struct hci_dev *hdev, u8 scan)
{}

int hci_dev_cmd(unsigned int cmd, void __user *arg)
{}

int hci_get_dev_list(void __user *arg)
{}

int hci_get_dev_info(void __user *arg)
{}

/* ---- Interface to HCI drivers ---- */

static int hci_dev_do_poweroff(struct hci_dev *hdev)
{}

static int hci_rfkill_set_block(void *data, bool blocked)
{}

static const struct rfkill_ops hci_rfkill_ops =;

static void hci_power_on(struct work_struct *work)
{}

static void hci_power_off(struct work_struct *work)
{}

static void hci_error_reset(struct work_struct *work)
{}

void hci_uuids_clear(struct hci_dev *hdev)
{}

void hci_link_keys_clear(struct hci_dev *hdev)
{}

void hci_smp_ltks_clear(struct hci_dev *hdev)
{}

void hci_smp_irks_clear(struct hci_dev *hdev)
{}

void hci_blocked_keys_clear(struct hci_dev *hdev)
{}

bool hci_is_blocked_key(struct hci_dev *hdev, u8 type, u8 val[16])
{}

struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
{}

static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
			       u8 key_type, u8 old_key_type)
{}

static u8 ltk_role(u8 type)
{}

struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
			     u8 addr_type, u8 role)
{}

struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa)
{}

struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
				     u8 addr_type)
{}

struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
				  bdaddr_t *bdaddr, u8 *val, u8 type,
				  u8 pin_len, bool *persistent)
{}

struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
			    u8 addr_type, u8 type, u8 authenticated,
			    u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand)
{}

struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
			    u8 addr_type, u8 val[16], bdaddr_t *rpa)
{}

int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
{}

int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
{}

void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type)
{}

bool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
{}

/* HCI command timer function */
static void hci_cmd_timeout(struct work_struct *work)
{}

/* HCI ncmd timer function */
static void hci_ncmd_timeout(struct work_struct *work)
{}

struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
					  bdaddr_t *bdaddr, u8 bdaddr_type)
{}

int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
			       u8 bdaddr_type)
{}

void hci_remote_oob_data_clear(struct hci_dev *hdev)
{}

int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
			    u8 bdaddr_type, u8 *hash192, u8 *rand192,
			    u8 *hash256, u8 *rand256)
{}

/* This function requires the caller holds hdev->lock */
struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance)
{}

/* This function requires the caller holds hdev->lock */
struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance)
{}

/* This function requires the caller holds hdev->lock */
int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance)
{}

void hci_adv_instances_set_rpa_expired(struct hci_dev *hdev, bool rpa_expired)
{}

/* This function requires the caller holds hdev->lock */
void hci_adv_instances_clear(struct hci_dev *hdev)
{}

static void adv_instance_rpa_expired(struct work_struct *work)
{}

/* This function requires the caller holds hdev->lock */
struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
				      u32 flags, u16 adv_data_len, u8 *adv_data,
				      u16 scan_rsp_len, u8 *scan_rsp_data,
				      u16 timeout, u16 duration, s8 tx_power,
				      u32 min_interval, u32 max_interval,
				      u8 mesh_handle)
{}

/* This function requires the caller holds hdev->lock */
struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance,
				      u32 flags, u8 data_len, u8 *data,
				      u32 min_interval, u32 max_interval)
{}

/* This function requires the caller holds hdev->lock */
int hci_set_adv_instance_data(struct hci_dev *hdev, u8 instance,
			      u16 adv_data_len, u8 *adv_data,
			      u16 scan_rsp_len, u8 *scan_rsp_data)
{}

/* This function requires the caller holds hdev->lock */
u32 hci_adv_instance_flags(struct hci_dev *hdev, u8 instance)
{}

bool hci_adv_instance_is_scannable(struct hci_dev *hdev, u8 instance)
{}

/* This function requires the caller holds hdev->lock */
void hci_adv_monitors_clear(struct hci_dev *hdev)
{}

/* Frees the monitor structure and do some bookkeepings.
 * This function requires the caller holds hdev->lock.
 */
void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
{}

/* Assigns handle to a monitor, and if offloading is supported and power is on,
 * also attempts to forward the request to the controller.
 * This function requires the caller holds hci_req_sync_lock.
 */
int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
{}

/* Attempts to tell the controller and free the monitor. If somehow the
 * controller doesn't have a corresponding handle, remove anyway.
 * This function requires the caller holds hci_req_sync_lock.
 */
static int hci_remove_adv_monitor(struct hci_dev *hdev,
				  struct adv_monitor *monitor)
{}

/* This function requires the caller holds hci_req_sync_lock */
int hci_remove_single_adv_monitor(struct hci_dev *hdev, u16 handle)
{}

/* This function requires the caller holds hci_req_sync_lock */
int hci_remove_all_adv_monitor(struct hci_dev *hdev)
{}

/* This function requires the caller holds hdev->lock */
bool hci_is_adv_monitoring(struct hci_dev *hdev)
{}

int hci_get_adv_monitor_offload_ext(struct hci_dev *hdev)
{}

struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list,
					 bdaddr_t *bdaddr, u8 type)
{}

struct bdaddr_list_with_irk *hci_bdaddr_list_lookup_with_irk(
				struct list_head *bdaddr_list, bdaddr_t *bdaddr,
				u8 type)
{}

struct bdaddr_list_with_flags *
hci_bdaddr_list_lookup_with_flags(struct list_head *bdaddr_list,
				  bdaddr_t *bdaddr, u8 type)
{}

void hci_bdaddr_list_clear(struct list_head *bdaddr_list)
{}

int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type)
{}

int hci_bdaddr_list_add_with_irk(struct list_head *list, bdaddr_t *bdaddr,
					u8 type, u8 *peer_irk, u8 *local_irk)
{}

int hci_bdaddr_list_add_with_flags(struct list_head *list, bdaddr_t *bdaddr,
				   u8 type, u32 flags)
{}

int hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type)
{}

int hci_bdaddr_list_del_with_irk(struct list_head *list, bdaddr_t *bdaddr,
							u8 type)
{}

int hci_bdaddr_list_del_with_flags(struct list_head *list, bdaddr_t *bdaddr,
				   u8 type)
{}

/* This function requires the caller holds hdev->lock */
struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
					       bdaddr_t *addr, u8 addr_type)
{}

/* This function requires the caller holds hdev->lock or rcu_read_lock */
struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
						  bdaddr_t *addr, u8 addr_type)
{}

/* This function requires the caller holds hdev->lock */
void hci_pend_le_list_del_init(struct hci_conn_params *param)
{}

/* This function requires the caller holds hdev->lock */
void hci_pend_le_list_add(struct hci_conn_params *param,
			  struct list_head *list)
{}

/* This function requires the caller holds hdev->lock */
struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
					    bdaddr_t *addr, u8 addr_type)
{}

void hci_conn_params_free(struct hci_conn_params *params)
{}

/* This function requires the caller holds hdev->lock */
void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
{}

/* This function requires the caller holds hdev->lock */
void hci_conn_params_clear_disabled(struct hci_dev *hdev)
{}

/* This function requires the caller holds hdev->lock */
static void hci_conn_params_clear_all(struct hci_dev *hdev)
{}

/* Copy the Identity Address of the controller.
 *
 * If the controller has a public BD_ADDR, then by default use that one.
 * If this is a LE only controller without a public address, default to
 * the static random address.
 *
 * For debugging purposes it is possible to force controllers with a
 * public address to use the static random address instead.
 *
 * In case BR/EDR has been disabled on a dual-mode controller and
 * userspace has configured a static address, then that address
 * becomes the identity address instead of the public BR/EDR address.
 */
void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
			       u8 *bdaddr_type)
{}

static void hci_clear_wake_reason(struct hci_dev *hdev)
{}

static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
				void *data)
{}

/* Alloc HCI device */
struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
{}
EXPORT_SYMBOL();

/* Free HCI device */
void hci_free_dev(struct hci_dev *hdev)
{}
EXPORT_SYMBOL();

/* Register HCI device */
int hci_register_dev(struct hci_dev *hdev)
{}
EXPORT_SYMBOL();

/* Unregister HCI device */
void hci_unregister_dev(struct hci_dev *hdev)
{}
EXPORT_SYMBOL();

/* Release HCI device */
void hci_release_dev(struct hci_dev *hdev)
{}
EXPORT_SYMBOL();

int hci_register_suspend_notifier(struct hci_dev *hdev)
{}

int hci_unregister_suspend_notifier(struct hci_dev *hdev)
{}

/* Cancel ongoing command synchronously:
 *
 * - Cancel command timer
 * - Reset command counter
 * - Cancel command request
 */
static void hci_cancel_cmd_sync(struct hci_dev *hdev, int err)
{}

/* Suspend HCI device */
int hci_suspend_dev(struct hci_dev *hdev)
{}
EXPORT_SYMBOL();

/* Resume HCI device */
int hci_resume_dev(struct hci_dev *hdev)
{}
EXPORT_SYMBOL();

/* Reset HCI device */
int hci_reset_dev(struct hci_dev *hdev)
{}
EXPORT_SYMBOL();

static u8 hci_dev_classify_pkt_type(struct hci_dev *hdev, struct sk_buff *skb)
{}

/* Receive frame from HCI drivers */
int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
{}
EXPORT_SYMBOL();

/* Receive diagnostic message from HCI drivers */
int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb)
{}
EXPORT_SYMBOL();

void hci_set_hw_info(struct hci_dev *hdev, const char *fmt, ...)
{}
EXPORT_SYMBOL();

void hci_set_fw_info(struct hci_dev *hdev, const char *fmt, ...)
{}
EXPORT_SYMBOL();

/* ---- Interface to upper protocols ---- */

int hci_register_cb(struct hci_cb *cb)
{}
EXPORT_SYMBOL();

int hci_unregister_cb(struct hci_cb *cb)
{}
EXPORT_SYMBOL();

static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{}

/* Send HCI command */
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen,
		 const void *param)
{}

int __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen,
		   const void *param)
{}
EXPORT_SYMBOL();

/* Get data from the previously sent command */
static void *hci_cmd_data(struct sk_buff *skb, __u16 opcode)
{}

/* Get data from the previously sent command */
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
{}

/* Get data from last received event */
void *hci_recv_event_data(struct hci_dev *hdev, __u8 event)
{}

/* Send ACL data */
static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
{}

static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,
			  struct sk_buff *skb, __u16 flags)
{}

void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
{}

/* Send SCO data */
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
{}

/* Send ISO data */
static void hci_add_iso_hdr(struct sk_buff *skb, __u16 handle, __u8 flags)
{}

static void hci_queue_iso(struct hci_conn *conn, struct sk_buff_head *queue,
			  struct sk_buff *skb)
{}

void hci_send_iso(struct hci_conn *conn, struct sk_buff *skb)
{}

/* ---- HCI TX task (outgoing data) ---- */

/* HCI Connection scheduler */
static inline void hci_quote_sent(struct hci_conn *conn, int num, int *quote)
{}

static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type,
				     int *quote)
{}

static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
{}

static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
				      int *quote)
{}

static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
{}

static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type)
{}

/* Schedule SCO */
static void hci_sched_sco(struct hci_dev *hdev)
{}

static void hci_sched_esco(struct hci_dev *hdev)
{}

static void hci_sched_acl_pkt(struct hci_dev *hdev)
{}

static void hci_sched_acl(struct hci_dev *hdev)
{}

static void hci_sched_le(struct hci_dev *hdev)
{}

/* Schedule CIS */
static void hci_sched_iso(struct hci_dev *hdev)
{}

static void hci_tx_work(struct work_struct *work)
{}

/* ----- HCI RX task (incoming data processing) ----- */

/* ACL data packet */
static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
{}

/* SCO data packet */
static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
{}

static void hci_isodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
{}

static bool hci_req_is_complete(struct hci_dev *hdev)
{}

static void hci_resend_last(struct hci_dev *hdev)
{}

void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
			  hci_req_complete_t *req_complete,
			  hci_req_complete_skb_t *req_complete_skb)
{}

static void hci_rx_work(struct work_struct *work)
{}

static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
{}

static void hci_cmd_work(struct work_struct *work)
{}