Commit d876e551 authored by Maksim Krasnyanskiy's avatar Maksim Krasnyanskiy

RFCOMM core API extensions. Improved /proc/bluetooth/rfcomm format.

RFCOMM socket locking fixes. 
Fix typo in rfcomm_pi() macro, no more oopses on socket destruction. 
parent 730e1a09
......@@ -268,6 +268,7 @@ struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst);
struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *err);
void rfcomm_session_del(struct rfcomm_session *s);
void rfcomm_session_close(struct rfcomm_session *s, int err);
void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst);
static inline void rfcomm_session_hold(struct rfcomm_session *s)
{
......@@ -290,7 +291,7 @@ struct sockaddr_rc {
u8 rc_channel;
};
#define rfcomm_pi(sk) ((struct rfcomm_pinfo *) &sk->protinfo)
#define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk->protinfo)
struct rfcomm_pinfo {
struct rfcomm_dlc *dlc;
......
......@@ -42,6 +42,7 @@
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/net.h>
#include <linux/proc_fs.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
......@@ -572,6 +573,15 @@ struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst, int *
return NULL;
}
void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst)
{
struct sock *sk = s->sock->sk;
if (src)
bacpy(src, &bluez_sk(sk)->src);
if (dst)
bacpy(dst, &bluez_sk(sk)->dst);
}
/* ---- RFCOMM frame sending ---- */
static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len)
{
......@@ -1674,6 +1684,63 @@ static int rfcomm_run(void *unused)
return 0;
}
/* ---- Proc fs support ---- */
static int rfcomm_dlc_dump(char *buf)
{
struct rfcomm_session *s;
struct sock *sk;
struct list_head *p, *pp;
char *ptr = buf;
rfcomm_lock();
list_for_each(p, &session_list) {
s = list_entry(p, struct rfcomm_session, list);
sk = s->sock->sk;
list_for_each(pp, &s->dlcs) {
struct rfcomm_dlc *d;
d = list_entry(pp, struct rfcomm_dlc, list);
ptr += sprintf(ptr, "dlc %s %s %ld %d %d %d %d\n",
batostr(&bluez_sk(sk)->src), batostr(&bluez_sk(sk)->dst),
d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits);
}
}
rfcomm_unlock();
return ptr - buf;
}
extern int rfcomm_sock_dump(char *buf);
static int rfcomm_read_proc(char *buf, char **start, off_t offset, int count, int *eof, void *priv)
{
char *ptr = buf;
int len;
BT_DBG("count %d, offset %ld", count, offset);
ptr += rfcomm_dlc_dump(ptr);
ptr += rfcomm_sock_dump(ptr);
len = ptr - buf;
if (len <= count + offset)
*eof = 1;
*start = buf + offset;
len -= offset;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
}
/* ---- Initialization ---- */
int __init rfcomm_init(void)
{
kernel_thread(rfcomm_run, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
......@@ -1684,6 +1751,8 @@ int __init rfcomm_init(void)
rfcomm_init_ttys();
#endif
create_proc_read_entry("bluetooth/rfcomm", 0, 0, rfcomm_read_proc, NULL);
BT_INFO("BlueZ RFCOMM ver %s", VERSION);
BT_INFO("Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>");
BT_INFO("Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>");
......@@ -1701,6 +1770,8 @@ void rfcomm_cleanup(void)
while (atomic_read(&running))
schedule();
remove_proc_entry("bluetooth/rfcomm", NULL);
#ifdef CONFIG_BLUEZ_RFCOMM_TTY
rfcomm_cleanup_ttys();
#endif
......
......@@ -43,7 +43,6 @@
#include <linux/interrupt.h>
#include <linux/socket.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/list.h>
#include <net/sock.h>
......@@ -83,7 +82,6 @@ static void rfcomm_sk_data_ready(struct rfcomm_dlc *d, struct sk_buff *skb)
if (atomic_read(&sk->rmem_alloc) >= sk->rcvbuf)
rfcomm_dlc_throttle(d);
return;
}
static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
......@@ -94,22 +92,26 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
BT_DBG("dlc %p state %ld err %d", d, d->state, err);
bh_lock_sock(sk);
if (err)
sk->err = err;
sk->state = d->state;
parent = bluez_sk(sk)->parent;
if (!parent)
if (!parent) {
if (d->state == BT_CONNECTED)
rfcomm_session_getaddr(d->session, &bluez_sk(sk)->src, NULL);
sk->state_change(sk);
else
} else
parent->data_ready(parent, 0);
return;
bh_unlock_sock(sk);
}
static void rfcomm_sk_modem_status(struct rfcomm_dlc *d, int v24_sig)
{
BT_DBG("dlc %p v24_sig 0x%02x", d, v24_sig);
return;
}
......@@ -374,6 +376,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
sk->state = BT_CONNECT;
bacpy(&bluez_sk(sk)->dst, &sa->rc_bdaddr);
rfcomm_pi(sk)->channel = sa->rc_channel;
err = rfcomm_dlc_open(d, &bluez_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel);
if (!err)
......@@ -655,7 +658,6 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how)
return 0;
}
static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
{
struct sock *sk = sock->sk;
......@@ -735,14 +737,16 @@ static int rfcomm_sock_release(struct socket *sock)
*/
int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc **d)
{
struct bluez_sock *bsk = bluez_sk(s->sock->sk);
struct sock *sk, *parent;
bdaddr_t src, dst;
int result = 0;
BT_DBG("session %p channel %d", s, channel);
rfcomm_session_getaddr(s, &src, &dst);
/* Check if we have socket listening on channel */
parent = rfcomm_get_sock_by_channel(BT_LISTEN, channel, &bsk->src);
parent = rfcomm_get_sock_by_channel(BT_LISTEN, channel, &src);
if (!parent)
return 0;
......@@ -757,8 +761,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
goto done;
rfcomm_sock_init(sk, parent);
bacpy(&bluez_sk(sk)->src, &bsk->src);
bacpy(&bluez_sk(sk)->dst, &bsk->dst);
bacpy(&bluez_sk(sk)->src, &src);
bacpy(&bluez_sk(sk)->dst, &dst);
rfcomm_pi(sk)->channel = channel;
sk->state = BT_CONFIG;
......@@ -774,8 +778,9 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
}
/* ---- Proc fs support ---- */
static int rfcomm_sock_dump(char *buf, struct bluez_sock_list *list)
int rfcomm_sock_dump(char *buf)
{
struct bluez_sock_list *list = &rfcomm_sk_list;
struct rfcomm_pinfo *pi;
struct sock *sk;
char *ptr = buf;
......@@ -784,42 +789,16 @@ static int rfcomm_sock_dump(char *buf, struct bluez_sock_list *list)
for (sk = list->head; sk; sk = sk->next) {
pi = rfcomm_pi(sk);
ptr += sprintf(ptr, "%s %s %d %d\n",
ptr += sprintf(ptr, "sk %s %s %d %d\n",
batostr(&bluez_sk(sk)->src), batostr(&bluez_sk(sk)->dst),
sk->state, rfcomm_pi(sk)->channel);
sk->state, rfcomm_pi(sk)->channel);
}
write_unlock_bh(&list->lock);
ptr += sprintf(ptr, "\n");
return ptr - buf;
}
static int rfcomm_read_proc(char *buf, char **start, off_t offset, int count, int *eof, void *priv)
{
char *ptr = buf;
int len;
BT_DBG("count %d, offset %ld", count, offset);
ptr += rfcomm_sock_dump(ptr, &rfcomm_sk_list);
len = ptr - buf;
if (len <= count + offset)
*eof = 1;
*start = buf + offset;
len -= offset;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
}
static struct proto_ops rfcomm_sock_ops = {
.family = PF_BLUETOOTH,
.release = rfcomm_sock_release,
......@@ -853,7 +832,6 @@ int rfcomm_init_sockets(void)
return err;
}
create_proc_read_entry("bluetooth/rfcomm", 0, 0, rfcomm_read_proc, NULL);
return 0;
}
......@@ -861,8 +839,6 @@ void rfcomm_cleanup_sockets(void)
{
int err;
remove_proc_entry("bluetooth/rfcomm", NULL);
/* Unregister socket, protocol and notifier */
if ((err = bluez_sock_unregister(BTPROTO_RFCOMM)))
BT_ERR("Can't unregister RFCOMM socket layer %d", err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment