X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fbluetooth%2Frfcomm%2Fcore.c;h=52e04df323eaa61eebb326659bf84c2db0cc52a8;hb=6ec129c3a2f8b38bc37e42348470ccfcb7460146;hp=278c8676906a3d345c00498256973b4b91533c57;hpb=ec0bf39a471bf6fcd01def2bd677128cea940b73;p=pandora-kernel.git diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 278c8676906a..52e04df323ea 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1,4 +1,4 @@ -/* +/* RFCOMM implementation for Linux Bluetooth stack (BlueZ). Copyright (C) 2002 Maxim Krasnyansky Copyright (C) 2002 Marcel Holtmann @@ -11,13 +11,13 @@ 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 + 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 + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED. */ @@ -134,7 +134,7 @@ static inline void rfcomm_session_put(struct rfcomm_session *s) /* ---- RFCOMM FCS computation ---- */ /* reversed, 8-bit, poly=0x07 */ -static unsigned char rfcomm_crc_table[256] = { +static unsigned char rfcomm_crc_table[256] = { 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, @@ -179,13 +179,13 @@ static unsigned char rfcomm_crc_table[256] = { /* CRC on 2 bytes */ #define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]]) -/* FCS on 2 bytes */ +/* FCS on 2 bytes */ static inline u8 __fcs(u8 *data) { return (0xff - __crc(data)); } -/* FCS on 3 bytes */ +/* FCS on 3 bytes */ static inline u8 __fcs2(u8 *data) { return (0xff - rfcomm_crc_table[__crc(data) ^ data[2]]); @@ -288,7 +288,7 @@ struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio) atomic_set(&d->refcnt, 1); rfcomm_dlc_clear_state(d); - + BT_DBG("%p", d); return d; @@ -345,7 +345,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, int err = 0; u8 dlci; - BT_DBG("dlc %p state %ld %s %s channel %d", + BT_DBG("dlc %p state %ld %s %s channel %d", d, d->state, batostr(src), batostr(dst), channel); if (channel < 1 || channel > 30) @@ -489,21 +489,21 @@ void fastcall __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) rfcomm_schedule(RFCOMM_SCHED_TX); } -/* +/* Set/get modem status functions use _local_ status i.e. what we report to the other side. Remote status is provided by dlc->modem_status() callback. */ int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig) { - BT_DBG("dlc %p state %ld v24_sig 0x%x", + BT_DBG("dlc %p state %ld v24_sig 0x%x", d, d->state, v24_sig); if (test_bit(RFCOMM_RX_THROTTLED, &d->flags)) v24_sig |= RFCOMM_V24_FC; else v24_sig &= ~RFCOMM_V24_FC; - + d->v24_sig = v24_sig; if (!test_and_set_bit(RFCOMM_MSC_PENDING, &d->flags)) @@ -514,7 +514,7 @@ int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig) int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig) { - BT_DBG("dlc %p state %ld v24_sig 0x%x", + BT_DBG("dlc %p state %ld v24_sig 0x%x", d, d->state, d->v24_sig); *v24_sig = d->v24_sig; @@ -576,7 +576,7 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) struct bt_sock *sk; list_for_each_safe(p, n, &session_list) { s = list_entry(p, struct rfcomm_session, list); - sk = bt_sk(s->sock->sk); + sk = bt_sk(s->sock->sk); if ((!bacmp(src, BDADDR_ANY) || !bacmp(&sk->src, src)) && !bacmp(&sk->dst, dst)) @@ -622,7 +622,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst bacpy(&addr.l2_bdaddr, src); addr.l2_family = AF_BLUETOOTH; addr.l2_psm = 0; - *err = sock->ops->bind(sock, (struct sockaddr *) &addr, sizeof(addr)); + *err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); if (*err < 0) goto failed; @@ -643,7 +643,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst bacpy(&addr.l2_bdaddr, dst); addr.l2_family = AF_BLUETOOTH; addr.l2_psm = htobs(RFCOMM_PSM); - *err = sock->ops->connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); + *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); if (*err == 0 || *err == -EINPROGRESS) return s; @@ -825,7 +825,7 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, u8 bit_rate, u8 data_bits, u8 stop_bits, - u8 parity, u8 flow_ctrl_settings, + u8 parity, u8 flow_ctrl_settings, u8 xon_char, u8 xoff_char, u16 param_mask) { struct rfcomm_hdr *hdr; @@ -834,8 +834,8 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, u8 buf[16], *ptr = buf; BT_DBG("%p cr %d dlci %d bit_r 0x%x data_b 0x%x stop_b 0x%x parity 0x%x" - " flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x", - s, cr, dlci, bit_rate, data_bits, stop_bits, parity, + " flwc_s 0x%x xon_c 0x%x xoff_c 0x%x p_mask 0x%x", + s, cr, dlci, bit_rate, data_bits, stop_bits, parity, flow_ctrl_settings, xon_char, xoff_char, param_mask); hdr = (void *) ptr; ptr += sizeof(*hdr); @@ -1058,6 +1058,12 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) case BT_DISCONN: d->state = BT_CLOSED; __rfcomm_dlc_close(d, 0); + + if (list_empty(&s->dlcs)) { + s->state = BT_DISCONN; + rfcomm_send_disc(s, 0); + } + break; } } else { @@ -1067,6 +1073,10 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) s->state = BT_CONNECTED; rfcomm_process_connect(s); break; + + case BT_DISCONN: + rfcomm_session_put(s); + break; } } return 0; @@ -1120,9 +1130,9 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci) d->state = BT_CLOSED; __rfcomm_dlc_close(d, err); - } else + } else rfcomm_send_dm(s, dlci); - + } else { rfcomm_send_ua(s, 0); @@ -1230,7 +1240,7 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) { struct rfcomm_session *s = d->session; - BT_DBG("dlc %p state %ld dlci %d mtu %d fc 0x%x credits %d", + BT_DBG("dlc %p state %ld dlci %d mtu %d fc 0x%x credits %d", d, d->state, d->dlci, pn->mtu, pn->flow_ctrl, pn->credits); if ((pn->flow_ctrl == 0xf0 && s->cfc != RFCOMM_CFC_DISABLED) || @@ -1454,7 +1464,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb if (d->modem_status) d->modem_status(d, msc->v24_sig); rfcomm_dlc_unlock(d); - + rfcomm_send_msc(s, 0, dlci, msc->v24_sig); d->mscex |= RFCOMM_MSCEX_RX; @@ -1567,7 +1577,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) /* Trim FCS */ skb->len--; skb->tail--; - fcs = *(u8 *) skb->tail; + fcs = *(u8 *)skb_tail_pointer(skb); if (__check_fcs(skb->data, type, fcs)) { BT_ERR("bad checksum in packet"); @@ -1641,18 +1651,18 @@ static inline int rfcomm_process_tx(struct rfcomm_dlc *d) struct sk_buff *skb; int err; - BT_DBG("dlc %p state %ld cfc %d rx_credits %d tx_credits %d", + BT_DBG("dlc %p state %ld cfc %d rx_credits %d tx_credits %d", d, d->state, d->cfc, d->rx_credits, d->tx_credits); /* Send pending MSC */ if (test_and_clear_bit(RFCOMM_MSC_PENDING, &d->flags)) - rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig); + rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig); if (d->cfc) { - /* CFC enabled. + /* CFC enabled. * Give them some credits */ if (!test_bit(RFCOMM_RX_THROTTLED, &d->flags) && - d->rx_credits <= (d->cfc >> 2)) { + d->rx_credits <= (d->cfc >> 2)) { rfcomm_send_credits(d->session, d->addr, d->cfc - d->rx_credits); d->rx_credits = d->cfc; } @@ -1757,19 +1767,12 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) BT_DBG("session %p", s); - if (sock_create_lite(PF_BLUETOOTH, sock->type, BTPROTO_L2CAP, &nsock)) + err = kernel_accept(sock, &nsock, O_NONBLOCK); + if (err < 0) return; - nsock->ops = sock->ops; - __module_get(nsock->ops->owner); - err = sock->ops->accept(sock, nsock, O_NONBLOCK); - if (err < 0) { - sock_release(nsock); - return; - } - /* Set our callbacks */ nsock->sk->sk_data_ready = rfcomm_l2data_ready; nsock->sk->sk_state_change = rfcomm_l2state_change; @@ -1851,18 +1854,18 @@ static void rfcomm_worker(void) BT_DBG(""); while (!atomic_read(&terminate)) { + set_current_state(TASK_INTERRUPTIBLE); if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) { /* No pending events. Let's sleep. * Incoming connections and data will wake us up. */ - set_current_state(TASK_INTERRUPTIBLE); schedule(); } + set_current_state(TASK_RUNNING); /* Process stuff */ clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event); rfcomm_process_sessions(); } - set_current_state(TASK_RUNNING); return; } @@ -1876,7 +1879,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) /* Create socket */ err = rfcomm_l2sock_create(&sock); - if (err < 0) { + if (err < 0) { BT_ERR("Create socket failed %d", err); return err; } @@ -1885,7 +1888,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) bacpy(&addr.l2_bdaddr, ba); addr.l2_family = AF_BLUETOOTH; addr.l2_psm = htobs(RFCOMM_PSM); - err = sock->ops->bind(sock, (struct sockaddr *) &addr, sizeof(addr)); + err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { BT_ERR("Bind failed %d", err); goto failed; @@ -1898,7 +1901,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) release_sock(sk); /* Start listening on the socket */ - err = sock->ops->listen(sock, 10); + err = kernel_listen(sock, 10); if (err) { BT_ERR("Listen failed %d", err); goto failed;