patch-2.4.19 linux-2.4.19/include/net/bluetooth/hci_core.h
Next file: linux-2.4.19/include/net/bluetooth/hci_uart.h
Previous file: linux-2.4.19/include/net/bluetooth/hci.h
Back to the patch index
Back to the overall index
- Lines: 586
- Date:
Fri Aug 2 17:39:46 2002
- Orig file:
linux-2.4.18/include/net/bluetooth/hci_core.h
- Orig date:
Fri Sep 7 09:28:38 2001
diff -urN linux-2.4.18/include/net/bluetooth/hci_core.h linux-2.4.19/include/net/bluetooth/hci_core.h
@@ -23,7 +23,7 @@
*/
/*
- * $Id: hci_core.h,v 1.11 2001/08/05 06:02:15 maxk Exp $
+ * $Id: hci_core.h,v 1.4 2002/06/25 22:04:43 maxk Exp $
*/
#ifndef __HCI_CORE_H
@@ -32,14 +32,12 @@
#include <net/bluetooth/hci.h>
/* HCI upper protocols */
-#define HCI_MAX_PROTO 1
#define HCI_PROTO_L2CAP 0
+#define HCI_PROTO_SCO 1
#define HCI_INIT_TIMEOUT (HZ * 10)
-/* ----- Inquiry cache ----- */
-#define INQUIRY_CACHE_AGE_MAX (HZ*5) // 5 seconds
-#define INQUIRY_ENTRY_AGE_MAX (HZ*60) // 60 seconds
+/* HCI Core structures */
struct inquiry_entry {
struct inquiry_entry *next;
@@ -53,111 +51,180 @@
struct inquiry_entry *list;
};
-static inline void inquiry_cache_init(struct inquiry_cache *cache)
-{
- spin_lock_init(&cache->lock);
- cache->list = NULL;
-}
+struct conn_hash {
+ struct list_head list;
+ spinlock_t lock;
+ unsigned int num;
+};
-static inline void inquiry_cache_lock(struct inquiry_cache *cache)
-{
- spin_lock(&cache->lock);
-}
+struct hci_dev {
+ struct list_head list;
+ spinlock_t lock;
+ atomic_t refcnt;
-static inline void inquiry_cache_unlock(struct inquiry_cache *cache)
-{
- spin_unlock(&cache->lock);
-}
+ char name[8];
+ unsigned long flags;
+ __u16 id;
+ __u8 type;
+ bdaddr_t bdaddr;
+ __u8 features[8];
-static inline void inquiry_cache_lock_bh(struct inquiry_cache *cache)
-{
- spin_lock_bh(&cache->lock);
-}
+ __u16 pkt_type;
+ __u16 link_policy;
+ __u16 link_mode;
+
+ atomic_t cmd_cnt;
+ unsigned int acl_cnt;
+ unsigned int sco_cnt;
-static inline void inquiry_cache_unlock_bh(struct inquiry_cache *cache)
-{
- spin_unlock_bh(&cache->lock);
-}
+ unsigned int acl_mtu;
+ unsigned int sco_mtu;
+ unsigned int acl_pkts;
+ unsigned int sco_pkts;
-static inline long inquiry_cache_age(struct inquiry_cache *cache)
-{
- return jiffies - cache->timestamp;
-}
+ unsigned long cmd_last_tx;
+ unsigned long acl_last_tx;
+ unsigned long sco_last_tx;
+
+ struct tasklet_struct cmd_task;
+ struct tasklet_struct rx_task;
+ struct tasklet_struct tx_task;
-static inline long inquiry_entry_age(struct inquiry_entry *e)
-{
- return jiffies - e->timestamp;
-}
-extern void inquiry_cache_flush(struct inquiry_cache *cache);
+ struct sk_buff_head rx_q;
+ struct sk_buff_head raw_q;
+ struct sk_buff_head cmd_q;
-struct hci_dev;
+ struct sk_buff *sent_cmd;
+
+ struct semaphore req_lock;
+ wait_queue_head_t req_wait_q;
+ __u32 req_status;
+ __u32 req_result;
+
+ struct inquiry_cache inq_cache;
+ struct conn_hash conn_hash;
+
+ struct hci_dev_stats stat;
+
+ void *driver_data;
+ void *core_data;
+
+ atomic_t promisc;
+
+ int (*open)(struct hci_dev *hdev);
+ int (*close)(struct hci_dev *hdev);
+ int (*flush)(struct hci_dev *hdev);
+ int (*send)(struct sk_buff *skb);
+ void (*destruct)(struct hci_dev *hdev);
+ int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
+};
-/* ----- HCI Connections ----- */
struct hci_conn {
struct list_head list;
+
+ atomic_t refcnt;
+ spinlock_t lock;
+
bdaddr_t dst;
__u16 handle;
+ __u16 state;
__u8 type;
- unsigned int sent;
+ __u8 out;
+ __u32 link_mode;
+ unsigned long pend;
+
+ unsigned int sent;
+
+ struct sk_buff_head data_q;
+ struct timer_list timer;
+
struct hci_dev *hdev;
void *l2cap_data;
+ void *sco_data;
void *priv;
- struct sk_buff_head data_q;
+ struct hci_conn *link;
};
-struct conn_hash {
- struct list_head list;
- spinlock_t lock;
- unsigned int num;
-};
+extern struct hci_proto *hci_proto[];
+extern struct list_head hdev_list;
+extern spinlock_t hdev_list_lock;
+
+/* ----- Inquiry cache ----- */
+#define INQUIRY_CACHE_AGE_MAX (HZ*30) // 30 seconds
+#define INQUIRY_ENTRY_AGE_MAX (HZ*60) // 60 seconds
+
+#define inquiry_cache_lock(c) spin_lock(&c->lock)
+#define inquiry_cache_unlock(c) spin_unlock(&c->lock)
+#define inquiry_cache_lock_bh(c) spin_lock_bh(&c->lock)
+#define inquiry_cache_unlock_bh(c) spin_unlock_bh(&c->lock)
-static inline void conn_hash_init(struct conn_hash *h)
+static inline void inquiry_cache_init(struct hci_dev *hdev)
{
- INIT_LIST_HEAD(&h->list);
- spin_lock_init(&h->lock);
- h->num = 0;
+ struct inquiry_cache *c = &hdev->inq_cache;
+ spin_lock_init(&c->lock);
+ c->list = NULL;
}
-static inline void conn_hash_lock(struct conn_hash *h)
+static inline long inquiry_cache_age(struct hci_dev *hdev)
{
- spin_lock(&h->lock);
+ struct inquiry_cache *c = &hdev->inq_cache;
+ return jiffies - c->timestamp;
}
-static inline void conn_hash_unlock(struct conn_hash *h)
+static inline long inquiry_entry_age(struct inquiry_entry *e)
{
- spin_unlock(&h->lock);
+ return jiffies - e->timestamp;
}
-static inline void __conn_hash_add(struct conn_hash *h, __u16 handle, struct hci_conn *c)
+struct inquiry_entry *inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+void inquiry_cache_update(struct hci_dev *hdev, inquiry_info *info);
+void inquiry_cache_flush(struct hci_dev *hdev);
+int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf);
+
+/* ----- HCI Connections ----- */
+enum {
+ HCI_CONN_AUTH_PEND,
+ HCI_CONN_ENCRYPT_PEND
+};
+
+#define hci_conn_lock(c) spin_lock(&c->lock)
+#define hci_conn_unlock(c) spin_unlock(&c->lock)
+#define hci_conn_lock_bh(c) spin_lock_bh(&c->lock)
+#define hci_conn_unlock_bh(c) spin_unlock_bh(&c->lock)
+
+#define conn_hash_lock(d) spin_lock(&d->conn_hash->lock)
+#define conn_hash_unlock(d) spin_unlock(&d->conn_hash->lock)
+#define conn_hash_lock_bh(d) spin_lock_bh(&d->conn_hash->lock)
+#define conn_hash_unlock_bh(d) spin_unlock_bh(&d->conn_hash->lock)
+
+static inline void conn_hash_init(struct hci_dev *hdev)
{
- list_add(&c->list, &h->list);
- h->num++;
+ struct conn_hash *h = &hdev->conn_hash;
+ INIT_LIST_HEAD(&h->list);
+ spin_lock_init(&h->lock);
+ h->num = 0;
}
-static inline void conn_hash_add(struct conn_hash *h, __u16 handle, struct hci_conn *c)
+static inline void conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
{
- conn_hash_lock(h);
- __conn_hash_add(h, handle, c);
- conn_hash_unlock(h);
+ struct conn_hash *h = &hdev->conn_hash;
+ list_add(&c->list, &h->list);
+ h->num++;
}
-static inline void __conn_hash_del(struct conn_hash *h, struct hci_conn *c)
+static inline void conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
{
+ struct conn_hash *h = &hdev->conn_hash;
list_del(&c->list);
h->num--;
}
-static inline void conn_hash_del(struct conn_hash *h, struct hci_conn *c)
-{
- conn_hash_lock(h);
- __conn_hash_del(h, c);
- conn_hash_unlock(h);
-}
-
-static inline struct hci_conn *__conn_hash_lookup(struct conn_hash *h, __u16 handle)
+static inline struct hci_conn *conn_hash_lookup_handle(struct hci_dev *hdev,
+ __u16 handle)
{
+ register struct conn_hash *h = &hdev->conn_hash;
register struct list_head *p;
register struct hci_conn *c;
@@ -169,101 +236,89 @@
return NULL;
}
-static inline struct hci_conn *conn_hash_lookup(struct conn_hash *h, __u16 handle)
+static inline struct hci_conn *conn_hash_lookup_ba(struct hci_dev *hdev,
+ __u8 type, bdaddr_t *ba)
{
- struct hci_conn *conn;
+ register struct conn_hash *h = &hdev->conn_hash;
+ register struct list_head *p;
+ register struct hci_conn *c;
- conn_hash_lock(h);
- conn = __conn_hash_lookup(h, handle);
- conn_hash_unlock(h);
- return conn;
+ list_for_each(p, &h->list) {
+ c = list_entry(p, struct hci_conn, list);
+ if (c->type == type && !bacmp(&c->dst, ba))
+ return c;
+ }
+ return NULL;
}
-/* ----- HCI Devices ----- */
-struct hci_dev {
- atomic_t refcnt;
-
- char name[8];
- __u32 flags;
- __u16 id;
- __u8 type;
- bdaddr_t bdaddr;
- __u8 features[8];
-
- __u16 pkt_type;
+void hci_acl_connect(struct hci_conn *conn);
+void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
+void hci_add_sco(struct hci_conn *conn, __u16 handle);
- atomic_t cmd_cnt;
- unsigned int acl_cnt;
- unsigned int sco_cnt;
+struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
+int hci_conn_del(struct hci_conn *conn);
+void hci_conn_hash_flush(struct hci_dev *hdev);
- unsigned int acl_mtu;
- unsigned int sco_mtu;
- unsigned int acl_max;
- unsigned int sco_max;
-
- void *driver_data;
- void *l2cap_data;
- void *priv;
-
- struct tasklet_struct cmd_task;
- struct tasklet_struct rx_task;
- struct tasklet_struct tx_task;
-
- struct sk_buff_head rx_q;
- struct sk_buff_head raw_q;
- struct sk_buff_head cmd_q;
-
- struct sk_buff *sent_cmd;
-
- struct semaphore req_lock;
- wait_queue_head_t req_wait_q;
- __u32 req_status;
- __u32 req_result;
-
- struct inquiry_cache inq_cache;
-
- struct conn_hash conn_hash;
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
+int hci_conn_auth(struct hci_conn *conn);
+int hci_conn_encrypt(struct hci_conn *conn);
- struct hci_dev_stats stat;
-
- int (*open)(struct hci_dev *hdev);
- int (*close)(struct hci_dev *hdev);
- int (*flush)(struct hci_dev *hdev);
- int (*send)(struct sk_buff *skb);
-};
+static inline void hci_conn_set_timer(struct hci_conn *conn, long timeout)
+{
+ mod_timer(&conn->timer, jiffies + timeout);
+}
-static inline void hci_dev_hold(struct hci_dev *hdev)
+static inline void hci_conn_del_timer(struct hci_conn *conn)
{
- atomic_inc(&hdev->refcnt);
+ del_timer(&conn->timer);
}
-static inline void hci_dev_put(struct hci_dev *hdev)
+static inline void hci_conn_hold(struct hci_conn *conn)
{
- atomic_dec(&hdev->refcnt);
+ atomic_inc(&conn->refcnt);
+ hci_conn_del_timer(conn);
}
-extern struct hci_dev *hci_dev_get(int index);
-extern int hci_register_dev(struct hci_dev *hdev);
-extern int hci_unregister_dev(struct hci_dev *hdev);
-extern int hci_dev_open(__u16 dev);
-extern int hci_dev_close(__u16 dev);
-extern int hci_dev_reset(__u16 dev);
-extern int hci_dev_reset_stat(__u16 dev);
-extern int hci_dev_info(unsigned long arg);
-extern int hci_dev_list(unsigned long arg);
-extern int hci_dev_setscan(unsigned long arg);
-extern int hci_dev_setauth(unsigned long arg);
-extern int hci_dev_setptype(unsigned long arg);
-extern int hci_conn_list(unsigned long arg);
-extern int hci_inquiry(unsigned long arg);
+static inline void hci_conn_put(struct hci_conn *conn)
+{
+ if (atomic_dec_and_test(&conn->refcnt) && conn->out)
+ hci_conn_set_timer(conn, HCI_DISCONN_TIMEOUT);
+}
-extern __u32 hci_dev_setmode(struct hci_dev *hdev, __u32 mode);
-extern __u32 hci_dev_getmode(struct hci_dev *hdev);
+/* ----- HCI Devices ----- */
+static inline void hci_dev_put(struct hci_dev *d)
+{
+ if (atomic_dec_and_test(&d->refcnt))
+ d->destruct(d);
+}
+#define hci_dev_hold(d) atomic_inc(&d->refcnt)
+
+#define hci_dev_lock(d) spin_lock(&d->lock)
+#define hci_dev_unlock(d) spin_unlock(&d->lock)
+#define hci_dev_lock_bh(d) spin_lock_bh(&d->lock)
+#define hci_dev_unlock_bh(d) spin_unlock_bh(&d->lock)
+
+struct hci_dev *hci_dev_get(int index);
+struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
+int hci_register_dev(struct hci_dev *hdev);
+int hci_unregister_dev(struct hci_dev *hdev);
+int hci_dev_open(__u16 dev);
+int hci_dev_close(__u16 dev);
+int hci_dev_reset(__u16 dev);
+int hci_dev_reset_stat(__u16 dev);
+int hci_dev_cmd(unsigned int cmd, unsigned long arg);
+int hci_get_dev_list(unsigned long arg);
+int hci_get_dev_info(unsigned long arg);
+int hci_get_conn_list(unsigned long arg);
+int hci_get_conn_info(struct hci_dev *hdev, unsigned long arg);
+int hci_inquiry(unsigned long arg);
-extern int hci_recv_frame(struct sk_buff *skb);
+int hci_recv_frame(struct sk_buff *skb);
+void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
/* ----- LMP capabilities ----- */
#define lmp_rswitch_capable(dev) (dev->features[0] & LMP_RSWITCH)
+#define lmp_encrypt_capable(dev) (dev->features[0] & LMP_ENCRYPT)
/* ----- HCI tasks ----- */
static inline void hci_sched_cmd(struct hci_dev *hdev)
@@ -284,43 +339,132 @@
/* ----- HCI protocols ----- */
struct hci_proto {
char *name;
- __u32 id;
- __u32 flags;
+ unsigned int id;
+ unsigned long flags;
void *priv;
- int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr);
- int (*connect_cfm) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 status, struct hci_conn *conn);
+ int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
+ int (*connect_cfm) (struct hci_conn *conn, __u8 status);
int (*disconn_ind) (struct hci_conn *conn, __u8 reason);
- int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb , __u16 flags);
+ int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
+ int (*auth_cfm) (struct hci_conn *conn, __u8 status);
+ int (*encrypt_cfm) (struct hci_conn *conn, __u8 status);
};
-extern int hci_register_proto(struct hci_proto *hproto);
-extern int hci_unregister_proto(struct hci_proto *hproto);
-extern int hci_register_notifier(struct notifier_block *nb);
-extern int hci_unregister_notifier(struct notifier_block *nb);
-extern int hci_connect(struct hci_dev * hdev, bdaddr_t * bdaddr);
-extern int hci_disconnect(struct hci_conn *conn, __u8 reason);
-extern int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void * param);
-extern int hci_send_raw(struct sk_buff *skb);
-extern int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
-extern int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
+static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
+{
+ register struct hci_proto *hp;
+ int mask = 0;
+
+ hp = hci_proto[HCI_PROTO_L2CAP];
+ if (hp && hp->connect_ind)
+ mask |= hp->connect_ind(hdev, bdaddr, type);
+
+ hp = hci_proto[HCI_PROTO_SCO];
+ if (hp && hp->connect_ind)
+ mask |= hp->connect_ind(hdev, bdaddr, type);
+
+ return mask;
+}
+
+static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
+{
+ register struct hci_proto *hp;
+
+ hp = hci_proto[HCI_PROTO_L2CAP];
+ if (hp && hp->connect_cfm)
+ hp->connect_cfm(conn, status);
+
+ hp = hci_proto[HCI_PROTO_SCO];
+ if (hp && hp->connect_cfm)
+ hp->connect_cfm(conn, status);
+}
+
+static inline void hci_proto_disconn_ind(struct hci_conn *conn, __u8 reason)
+{
+ register struct hci_proto *hp;
+
+ hp = hci_proto[HCI_PROTO_L2CAP];
+ if (hp && hp->disconn_ind)
+ hp->disconn_ind(conn, reason);
+
+ hp = hci_proto[HCI_PROTO_SCO];
+ if (hp && hp->disconn_ind)
+ hp->disconn_ind(conn, reason);
+}
+
+static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
+{
+ register struct hci_proto *hp;
+
+ hp = hci_proto[HCI_PROTO_L2CAP];
+ if (hp && hp->auth_cfm)
+ hp->auth_cfm(conn, status);
+
+ hp = hci_proto[HCI_PROTO_SCO];
+ if (hp && hp->auth_cfm)
+ hp->auth_cfm(conn, status);
+}
+
+static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status)
+{
+ register struct hci_proto *hp;
+
+ hp = hci_proto[HCI_PROTO_L2CAP];
+ if (hp && hp->encrypt_cfm)
+ hp->encrypt_cfm(conn, status);
+
+ hp = hci_proto[HCI_PROTO_SCO];
+ if (hp && hp->encrypt_cfm)
+ hp->encrypt_cfm(conn, status);
+}
+
+int hci_register_proto(struct hci_proto *hproto);
+int hci_unregister_proto(struct hci_proto *hproto);
+int hci_register_notifier(struct notifier_block *nb);
+int hci_unregister_notifier(struct notifier_block *nb);
+
+int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *param);
+int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
+int hci_send_raw(struct sk_buff *skb);
+
+void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf);
+
+void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data);
/* ----- HCI Sockets ----- */
-extern void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);
+void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);
/* HCI info for socket */
-#define hci_pi(sk) ((struct hci_pinfo *) &sk->protinfo)
+#define hci_pi(sk) ((struct hci_pinfo *) &sk->tp_pinfo)
struct hci_pinfo {
struct hci_dev *hdev;
struct hci_filter filter;
__u32 cmsg_mask;
};
+/* HCI security filter */
+#define HCI_SFLT_MAX_OGF 4
+
+struct hci_sec_filter {
+ __u32 type_mask;
+ __u32 event_mask[2];
+ __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4];
+};
+
+
/* ----- HCI requests ----- */
#define HCI_REQ_DONE 0
#define HCI_REQ_PEND 1
#define HCI_REQ_CANCELED 2
+#define hci_req_lock(d) down(&d->req_lock)
+#define hci_req_unlock(d) up(&d->req_lock)
+
+void hci_req_complete(struct hci_dev *hdev, int result);
+void hci_req_cancel(struct hci_dev *hdev, int err);
+
#endif /* __HCI_CORE_H */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)