aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-04-06 14:28:47 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-04-17 02:03:55 -0400
commit5205185d461d5902325e457ca80bd421127b7308 (patch)
tree9344c3d0c1f3647852e2db772583dfc5e467c484 /net/bluetooth
parentb4f34d8d9d26b2428fa7cf7c8f97690a297978e6 (diff)
Bluetooth: hidp: remove old session-management
We have the full new session-management now available so lets switch over and remove all the old code. Few semantics changed, so we need to adjust the sock.c callers a bit. But this mostly simplifies the logic. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hidp/core.c339
-rw-r--r--net/bluetooth/hidp/hidp.h6
-rw-r--r--net/bluetooth/hidp/sock.c21
3 files changed, 18 insertions, 348 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 8d30a33b27d9..481bbb8c7220 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -77,21 +77,7 @@ static inline void hidp_schedule(struct hidp_session *session)
77 wake_up_interruptible(sk_sleep(intr_sk)); 77 wake_up_interruptible(sk_sleep(intr_sk));
78} 78}
79 79
80static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr) 80static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
81{
82 struct hidp_session *session;
83
84 BT_DBG("");
85
86 list_for_each_entry(session, &hidp_session_list, list) {
87 if (!bacmp(bdaddr, &session->bdaddr))
88 return session;
89 }
90
91 return NULL;
92}
93
94static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
95{ 81{
96 memset(ci, 0, sizeof(*ci)); 82 memset(ci, 0, sizeof(*ci));
97 bacpy(&ci->bdaddr, &session->bdaddr); 83 bacpy(&ci->bdaddr, &session->bdaddr);
@@ -456,8 +442,7 @@ static void hidp_idle_timeout(unsigned long arg)
456{ 442{
457 struct hidp_session *session = (struct hidp_session *) arg; 443 struct hidp_session *session = (struct hidp_session *) arg;
458 444
459 atomic_inc(&session->terminate); 445 hidp_session_terminate(session);
460 wake_up_process(session->task);
461} 446}
462 447
463static void hidp_set_timer(struct hidp_session *session) 448static void hidp_set_timer(struct hidp_session *session)
@@ -525,8 +510,7 @@ static void hidp_process_hid_control(struct hidp_session *session,
525 skb_queue_purge(&session->ctrl_transmit); 510 skb_queue_purge(&session->ctrl_transmit);
526 skb_queue_purge(&session->intr_transmit); 511 skb_queue_purge(&session->intr_transmit);
527 512
528 atomic_inc(&session->terminate); 513 hidp_session_terminate(session);
529 wake_up_process(current);
530 } 514 }
531} 515}
532 516
@@ -686,120 +670,6 @@ static void hidp_process_ctrl_transmit(struct hidp_session *session)
686 } 670 }
687} 671}
688 672
689static int hidp_session(void *arg)
690{
691 struct hidp_session *session = arg;
692 struct sock *ctrl_sk = session->ctrl_sock->sk;
693 struct sock *intr_sk = session->intr_sock->sk;
694 struct sk_buff *skb;
695 wait_queue_t ctrl_wait, intr_wait;
696
697 BT_DBG("session %p", session);
698
699 __module_get(THIS_MODULE);
700 set_user_nice(current, -15);
701
702 init_waitqueue_entry(&ctrl_wait, current);
703 init_waitqueue_entry(&intr_wait, current);
704 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
705 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
706 session->waiting_for_startup = 0;
707 wake_up_interruptible(&session->startup_queue);
708 set_current_state(TASK_INTERRUPTIBLE);
709 while (!atomic_read(&session->terminate)) {
710 if (ctrl_sk->sk_state != BT_CONNECTED ||
711 intr_sk->sk_state != BT_CONNECTED)
712 break;
713
714 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
715 skb_orphan(skb);
716 if (!skb_linearize(skb))
717 hidp_recv_intr_frame(session, skb);
718 else
719 kfree_skb(skb);
720 }
721
722 hidp_process_intr_transmit(session);
723
724 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
725 skb_orphan(skb);
726 if (!skb_linearize(skb))
727 hidp_recv_ctrl_frame(session, skb);
728 else
729 kfree_skb(skb);
730 }
731
732 hidp_process_ctrl_transmit(session);
733
734 schedule();
735 set_current_state(TASK_INTERRUPTIBLE);
736 }
737 set_current_state(TASK_RUNNING);
738 atomic_inc(&session->terminate);
739 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
740 remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
741
742 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
743 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
744 wake_up_interruptible(&session->report_queue);
745
746 down_write(&hidp_session_sem);
747
748 hidp_del_timer(session);
749
750 if (session->input) {
751 input_unregister_device(session->input);
752 session->input = NULL;
753 }
754
755 if (session->hid) {
756 hid_destroy_device(session->hid);
757 session->hid = NULL;
758 }
759
760 /* Wakeup user-space polling for socket errors */
761 session->intr_sock->sk->sk_err = EUNATCH;
762 session->ctrl_sock->sk->sk_err = EUNATCH;
763
764 hidp_schedule(session);
765
766 fput(session->intr_sock->file);
767
768 wait_event_timeout(*(sk_sleep(ctrl_sk)),
769 (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
770
771 fput(session->ctrl_sock->file);
772
773 list_del(&session->list);
774
775 up_write(&hidp_session_sem);
776
777 kfree(session->rd_data);
778 kfree(session);
779 module_put_and_exit(0);
780 return 0;
781}
782
783static struct hci_conn *hidp_get_connection(struct hidp_session *session)
784{
785 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
786 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
787 struct hci_conn *conn;
788 struct hci_dev *hdev;
789
790 hdev = hci_get_route(dst, src);
791 if (!hdev)
792 return NULL;
793
794 hci_dev_lock(hdev);
795 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
796 hci_dev_unlock(hdev);
797
798 hci_dev_put(hdev);
799
800 return conn;
801}
802
803static int hidp_setup_input(struct hidp_session *session, 673static int hidp_setup_input(struct hidp_session *session,
804 struct hidp_connadd_req *req) 674 struct hidp_connadd_req *req)
805{ 675{
@@ -847,7 +717,7 @@ static int hidp_setup_input(struct hidp_session *session,
847 input->relbit[0] |= BIT_MASK(REL_WHEEL); 717 input->relbit[0] |= BIT_MASK(REL_WHEEL);
848 } 718 }
849 719
850 input->dev.parent = &session->hconn->dev; 720 input->dev.parent = &session->conn->hcon->dev;
851 721
852 input->event = hidp_input_event; 722 input->event = hidp_input_event;
853 723
@@ -951,7 +821,7 @@ static int hidp_setup_hid(struct hidp_session *session,
951 snprintf(hid->uniq, sizeof(hid->uniq), "%pMR", 821 snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
952 &bt_sk(session->ctrl_sock->sk)->dst); 822 &bt_sk(session->ctrl_sock->sk)->dst);
953 823
954 hid->dev.parent = &session->hconn->dev; 824 hid->dev.parent = &session->conn->hcon->dev;
955 hid->ll_driver = &hidp_hid_driver; 825 hid->ll_driver = &hidp_hid_driver;
956 826
957 hid->hid_get_raw_report = hidp_get_raw_report; 827 hid->hid_get_raw_report = hidp_get_raw_report;
@@ -1510,187 +1380,6 @@ int hidp_connection_del(struct hidp_conndel_req *req)
1510 return 0; 1380 return 0;
1511} 1381}
1512 1382
1513int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
1514{
1515 struct hidp_session *session, *s;
1516 int vendor, product;
1517 int err;
1518
1519 BT_DBG("");
1520
1521 if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock))
1522 return -EINVAL;
1523 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
1524 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
1525 return -ENOTUNIQ;
1526
1527 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
1528
1529 down_write(&hidp_session_sem);
1530
1531 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
1532 if (s) {
1533 up_write(&hidp_session_sem);
1534 return -EEXIST;
1535 }
1536
1537 session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
1538 if (!session) {
1539 up_write(&hidp_session_sem);
1540 return -ENOMEM;
1541 }
1542
1543 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
1544
1545 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
1546 l2cap_pi(ctrl_sock->sk)->chan->imtu);
1547 session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu,
1548 l2cap_pi(intr_sock->sk)->chan->imtu);
1549
1550 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
1551
1552 session->ctrl_sock = ctrl_sock;
1553 session->intr_sock = intr_sock;
1554
1555 session->hconn = hidp_get_connection(session);
1556 if (!session->hconn) {
1557 err = -ENOTCONN;
1558 goto failed;
1559 }
1560
1561 setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
1562
1563 skb_queue_head_init(&session->ctrl_transmit);
1564 skb_queue_head_init(&session->intr_transmit);
1565
1566 mutex_init(&session->report_mutex);
1567 init_waitqueue_head(&session->report_queue);
1568 init_waitqueue_head(&session->startup_queue);
1569 session->waiting_for_startup = 1;
1570 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1571 session->idle_to = req->idle_to;
1572
1573 list_add(&session->list, &hidp_session_list);
1574
1575 if (req->rd_size > 0) {
1576 err = hidp_setup_hid(session, req);
1577 if (err && err != -ENODEV)
1578 goto purge;
1579 }
1580
1581 if (!session->hid) {
1582 err = hidp_setup_input(session, req);
1583 if (err < 0)
1584 goto purge;
1585 }
1586
1587 hidp_set_timer(session);
1588
1589 if (session->hid) {
1590 vendor = session->hid->vendor;
1591 product = session->hid->product;
1592 } else if (session->input) {
1593 vendor = session->input->id.vendor;
1594 product = session->input->id.product;
1595 } else {
1596 vendor = 0x0000;
1597 product = 0x0000;
1598 }
1599
1600 session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
1601 vendor, product);
1602 if (IS_ERR(session->task)) {
1603 err = PTR_ERR(session->task);
1604 goto unlink;
1605 }
1606
1607 while (session->waiting_for_startup) {
1608 wait_event_interruptible(session->startup_queue,
1609 !session->waiting_for_startup);
1610 }
1611
1612 if (session->hid)
1613 err = hid_add_device(session->hid);
1614 else
1615 err = input_register_device(session->input);
1616
1617 if (err < 0) {
1618 atomic_inc(&session->terminate);
1619 wake_up_process(session->task);
1620 up_write(&hidp_session_sem);
1621 return err;
1622 }
1623
1624 if (session->input) {
1625 hidp_send_ctrl_message(session,
1626 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1627 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1628
1629 session->leds = 0xff;
1630 hidp_input_event(session->input, EV_LED, 0, 0);
1631 }
1632
1633 up_write(&hidp_session_sem);
1634 return 0;
1635
1636unlink:
1637 hidp_del_timer(session);
1638
1639 if (session->input) {
1640 input_unregister_device(session->input);
1641 session->input = NULL;
1642 }
1643
1644 if (session->hid) {
1645 hid_destroy_device(session->hid);
1646 session->hid = NULL;
1647 }
1648
1649 kfree(session->rd_data);
1650 session->rd_data = NULL;
1651
1652purge:
1653 list_del(&session->list);
1654
1655 skb_queue_purge(&session->ctrl_transmit);
1656 skb_queue_purge(&session->intr_transmit);
1657
1658failed:
1659 up_write(&hidp_session_sem);
1660
1661 kfree(session);
1662 return err;
1663}
1664
1665int hidp_del_connection(struct hidp_conndel_req *req)
1666{
1667 struct hidp_session *session;
1668 int err = 0;
1669
1670 BT_DBG("");
1671
1672 down_read(&hidp_session_sem);
1673
1674 session = __hidp_get_session(&req->bdaddr);
1675 if (session) {
1676 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1677 hidp_send_ctrl_message(session,
1678 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1679 } else {
1680 /* Flush the transmit queues */
1681 skb_queue_purge(&session->ctrl_transmit);
1682 skb_queue_purge(&session->intr_transmit);
1683
1684 atomic_inc(&session->terminate);
1685 wake_up_process(session->task);
1686 }
1687 } else
1688 err = -ENOENT;
1689
1690 up_read(&hidp_session_sem);
1691 return err;
1692}
1693
1694int hidp_get_connlist(struct hidp_connlist_req *req) 1383int hidp_get_connlist(struct hidp_connlist_req *req)
1695{ 1384{
1696 struct hidp_session *session; 1385 struct hidp_session *session;
@@ -1703,7 +1392,7 @@ int hidp_get_connlist(struct hidp_connlist_req *req)
1703 list_for_each_entry(session, &hidp_session_list, list) { 1392 list_for_each_entry(session, &hidp_session_list, list) {
1704 struct hidp_conninfo ci; 1393 struct hidp_conninfo ci;
1705 1394
1706 __hidp_copy_session(session, &ci); 1395 hidp_copy_session(session, &ci);
1707 1396
1708 if (copy_to_user(req->ci, &ci, sizeof(ci))) { 1397 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1709 err = -EFAULT; 1398 err = -EFAULT;
@@ -1724,18 +1413,14 @@ int hidp_get_connlist(struct hidp_connlist_req *req)
1724int hidp_get_conninfo(struct hidp_conninfo *ci) 1413int hidp_get_conninfo(struct hidp_conninfo *ci)
1725{ 1414{
1726 struct hidp_session *session; 1415 struct hidp_session *session;
1727 int err = 0;
1728 1416
1729 down_read(&hidp_session_sem); 1417 session = hidp_session_find(&ci->bdaddr);
1730 1418 if (session) {
1731 session = __hidp_get_session(&ci->bdaddr); 1419 hidp_copy_session(session, ci);
1732 if (session) 1420 hidp_session_put(session);
1733 __hidp_copy_session(session, ci); 1421 }
1734 else
1735 err = -ENOENT;
1736 1422
1737 up_read(&hidp_session_sem); 1423 return session ? 0 : -ENOENT;
1738 return err;
1739} 1424}
1740 1425
1741static int __init hidp_init(void) 1426static int __init hidp_init(void)
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index c4fb980c2434..6162ce8606ac 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -123,8 +123,6 @@ struct hidp_connlist_req {
123 123
124int hidp_connection_add(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock); 124int hidp_connection_add(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
125int hidp_connection_del(struct hidp_conndel_req *req); 125int hidp_connection_del(struct hidp_conndel_req *req);
126int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
127int hidp_del_connection(struct hidp_conndel_req *req);
128int hidp_get_connlist(struct hidp_connlist_req *req); 126int hidp_get_connlist(struct hidp_connlist_req *req);
129int hidp_get_conninfo(struct hidp_conninfo *ci); 127int hidp_get_conninfo(struct hidp_conninfo *ci);
130 128
@@ -147,7 +145,6 @@ struct hidp_session {
147 145
148 /* connection management */ 146 /* connection management */
149 bdaddr_t bdaddr; 147 bdaddr_t bdaddr;
150 struct hci_conn *hconn;
151 struct l2cap_conn *conn; 148 struct l2cap_conn *conn;
152 struct l2cap_user user; 149 struct l2cap_user user;
153 struct socket *ctrl_sock; 150 struct socket *ctrl_sock;
@@ -180,9 +177,6 @@ struct hidp_session {
180 177
181 /* Used in hidp_output_raw_report() */ 178 /* Used in hidp_output_raw_report() */
182 int output_report_success; /* boolean */ 179 int output_report_success; /* boolean */
183
184 wait_queue_head_t startup_queue;
185 int waiting_for_startup;
186}; 180};
187 181
188/* HIDP init defines */ 182/* HIDP init defines */
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index e6bf36a0ba40..2f4cbb0865ca 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -77,21 +77,12 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
77 return err; 77 return err;
78 } 78 }
79 79
80 if (csock->sk->sk_state != BT_CONNECTED || 80 err = hidp_connection_add(&ca, csock, isock);
81 isock->sk->sk_state != BT_CONNECTED) { 81 if (!err && copy_to_user(argp, &ca, sizeof(ca)))
82 sockfd_put(csock); 82 err = -EFAULT;
83 sockfd_put(isock);
84 return -EBADFD;
85 }
86 83
87 err = hidp_add_connection(&ca, csock, isock); 84 sockfd_put(csock);
88 if (!err) { 85 sockfd_put(isock);
89 if (copy_to_user(argp, &ca, sizeof(ca)))
90 err = -EFAULT;
91 } else {
92 sockfd_put(csock);
93 sockfd_put(isock);
94 }
95 86
96 return err; 87 return err;
97 88
@@ -102,7 +93,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
102 if (copy_from_user(&cd, argp, sizeof(cd))) 93 if (copy_from_user(&cd, argp, sizeof(cd)))
103 return -EFAULT; 94 return -EFAULT;
104 95
105 return hidp_del_connection(&cd); 96 return hidp_connection_del(&cd);
106 97
107 case HIDPGETCONNLIST: 98 case HIDPGETCONNLIST:
108 if (copy_from_user(&cl, argp, sizeof(cl))) 99 if (copy_from_user(&cl, argp, sizeof(cl)))