~ubuntu-branches/ubuntu/saucy/bluez/saucy

« back to all changes in this revision

Viewing changes to audio/avdtp.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2012-07-04 13:28:49 UTC
  • mfrom: (1.1.38)
  • Revision ID: package-import@ubuntu.com-20120704132849-tmwu1x7p2vxcclt1
Tags: 4.101-0ubuntu1
* New upstream release
* debian/libbluetooth3.symbols:
  - Updated
* debian/patches/10-unregister_interface_on_exit.patch:
* debian/patches/11-explicitly_close.patch:
* debian/patches/python3.patch:
  - Applied upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
#include <bluetooth/bluetooth.h>
39
39
#include <bluetooth/sdp.h>
40
40
#include <bluetooth/sdp_lib.h>
 
41
#include <bluetooth/uuid.h>
41
42
 
42
43
#include <glib.h>
43
44
#include <dbus/dbus.h>
52
53
#include "manager.h"
53
54
#include "control.h"
54
55
#include "avdtp.h"
55
 
#include "glib-compat.h"
56
56
#include "btio.h"
57
57
#include "sink.h"
58
58
#include "source.h"
314
314
        size_t data_size;
315
315
        struct avdtp_stream *stream; /* Set if the request targeted a stream */
316
316
        guint timeout;
 
317
        gboolean collided;
317
318
};
318
319
 
319
320
struct avdtp_remote_sep {
1067
1068
                break;
1068
1069
        case AVDTP_STATE_OPEN:
1069
1070
                stream->starting = FALSE;
1070
 
                if (old_state > AVDTP_STATE_OPEN && session->auto_dc)
 
1071
                if ((old_state > AVDTP_STATE_OPEN && session->auto_dc) ||
 
1072
                                                        stream->open_acp)
1071
1073
                        stream->idle_timer = g_timeout_add_seconds(STREAM_TIMEOUT,
1072
1074
                                                                stream_timeout,
1073
1075
                                                                stream);
1074
1076
                break;
1075
1077
        case AVDTP_STATE_STREAMING:
 
1078
                if (stream->idle_timer) {
 
1079
                        g_source_remove(stream->idle_timer);
 
1080
                        stream->idle_timer = 0;
 
1081
                }
 
1082
                stream->open_acp = FALSE;
 
1083
                break;
1076
1084
        case AVDTP_STATE_CLOSING:
1077
1085
        case AVDTP_STATE_ABORTING:
1078
1086
                if (stream->idle_timer) {
1520
1528
        case AVDTP_SEP_TYPE_SINK:
1521
1529
                if (!dev->source) {
1522
1530
                        btd_device_add_uuid(dev->btd_dev, A2DP_SOURCE_UUID);
1523
 
                        if (!dev->sink) {
 
1531
                        if (!dev->source) {
1524
1532
                                error("Unable to get a audio source object");
1525
1533
                                err = AVDTP_BAD_STATE;
1526
1534
                                goto failed;
1634
1642
static gboolean avdtp_reconf_cmd(struct avdtp *session, uint8_t transaction,
1635
1643
                                        struct seid_req *req, int size)
1636
1644
{
1637
 
        return avdtp_unknown_cmd(session, transaction, AVDTP_RECONFIGURE);
 
1645
        struct conf_rej rej;
 
1646
 
 
1647
        rej.error = AVDTP_NOT_SUPPORTED_COMMAND;
 
1648
        rej.category = 0x00;
 
1649
 
 
1650
        return avdtp_send(session, transaction, AVDTP_MSG_TYPE_REJECT,
 
1651
                                        AVDTP_RECONFIGURE, &rej, sizeof(rej));
 
1652
}
 
1653
 
 
1654
static void check_seid_collision(struct pending_req *req, uint8_t id)
 
1655
{
 
1656
        struct seid_req *seid = req->data;
 
1657
 
 
1658
        if (seid->acp_seid == id)
 
1659
                req->collided = TRUE;
 
1660
}
 
1661
 
 
1662
static void check_start_collision(struct pending_req *req, uint8_t id)
 
1663
{
 
1664
        struct start_req *start = req->data;
 
1665
        struct seid *seid = &start->first_seid;
 
1666
        int count = 1 + req->data_size - sizeof(struct start_req);
 
1667
        int i;
 
1668
 
 
1669
        for (i = 0; i < count; i++, seid++) {
 
1670
                if (seid->seid == id) {
 
1671
                        req->collided = TRUE;
 
1672
                        return;
 
1673
                }
 
1674
        }
 
1675
}
 
1676
 
 
1677
static void check_suspend_collision(struct pending_req *req, uint8_t id)
 
1678
{
 
1679
        struct suspend_req *suspend = req->data;
 
1680
        struct seid *seid = &suspend->first_seid;
 
1681
        int count = 1 + req->data_size - sizeof(struct suspend_req);
 
1682
        int i;
 
1683
 
 
1684
        for (i = 0; i < count; i++, seid++) {
 
1685
                if (seid->seid == id) {
 
1686
                        req->collided = TRUE;
 
1687
                        return;
 
1688
                }
 
1689
        }
 
1690
}
 
1691
 
 
1692
static void avdtp_check_collision(struct avdtp *session, uint8_t cmd,
 
1693
                                        struct avdtp_stream *stream)
 
1694
{
 
1695
        struct pending_req *req = session->req;
 
1696
 
 
1697
        if (req == NULL || (req->signal_id != cmd && cmd != AVDTP_ABORT))
 
1698
                return;
 
1699
 
 
1700
        if (cmd == AVDTP_ABORT)
 
1701
                cmd = req->signal_id;
 
1702
 
 
1703
        switch (cmd) {
 
1704
        case AVDTP_OPEN:
 
1705
        case AVDTP_CLOSE:
 
1706
                check_seid_collision(req, stream->rseid);
 
1707
                break;
 
1708
        case AVDTP_START:
 
1709
                check_start_collision(req, stream->rseid);
 
1710
                break;
 
1711
        case AVDTP_SUSPEND:
 
1712
                check_suspend_collision(req, stream->rseid);
 
1713
                break;
 
1714
        }
1638
1715
}
1639
1716
 
1640
1717
static gboolean avdtp_open_cmd(struct avdtp *session, uint8_t transaction,
1668
1745
                        goto failed;
1669
1746
        }
1670
1747
 
 
1748
        avdtp_check_collision(session, AVDTP_OPEN, stream);
 
1749
 
1671
1750
        if (!avdtp_send(session, transaction, AVDTP_MSG_TYPE_ACCEPT,
1672
1751
                                                AVDTP_OPEN, NULL, 0))
1673
1752
                return FALSE;
1716
1795
 
1717
1796
                stream = sep->stream;
1718
1797
 
1719
 
                /* Also reject start cmd if we already initiated start */
1720
 
                if (sep->state != AVDTP_STATE_OPEN ||
1721
 
                                                stream->starting == TRUE) {
 
1798
                /* Also reject start cmd if state is not open */
 
1799
                if (sep->state != AVDTP_STATE_OPEN) {
1722
1800
                        err = AVDTP_BAD_STATE;
1723
1801
                        goto failed;
1724
1802
                }
1730
1808
                                goto failed;
1731
1809
                }
1732
1810
 
 
1811
                avdtp_check_collision(session, AVDTP_START, stream);
 
1812
 
1733
1813
                avdtp_sep_set_state(session, sep, AVDTP_STATE_STREAMING);
1734
1814
        }
1735
1815
 
1777
1857
                        goto failed;
1778
1858
        }
1779
1859
 
 
1860
        avdtp_check_collision(session, AVDTP_CLOSE, stream);
 
1861
 
1780
1862
        avdtp_sep_set_state(session, sep, AVDTP_STATE_CLOSING);
1781
1863
 
1782
1864
        if (!avdtp_send(session, transaction, AVDTP_MSG_TYPE_ACCEPT,
1836
1918
                                goto failed;
1837
1919
                }
1838
1920
 
 
1921
                avdtp_check_collision(session, AVDTP_SUSPEND, stream);
 
1922
 
1839
1923
                avdtp_sep_set_state(session, sep, AVDTP_STATE_OPEN);
1840
1924
        }
1841
1925
 
1863
1947
        }
1864
1948
 
1865
1949
        sep = find_local_sep_by_seid(session->server, req->acp_seid);
1866
 
        if (!sep || !sep->stream) {
1867
 
                err = AVDTP_BAD_ACP_SEID;
1868
 
                goto failed;
1869
 
        }
1870
 
 
1871
 
        if (sep->ind && sep->ind->abort) {
1872
 
                if (!sep->ind->abort(session, sep, sep->stream, &err,
1873
 
                                        sep->user_data))
1874
 
                        goto failed;
1875
 
        }
 
1950
        if (!sep || !sep->stream)
 
1951
                return TRUE;
 
1952
 
 
1953
        if (sep->ind && sep->ind->abort)
 
1954
                sep->ind->abort(session, sep, sep->stream, &err,
 
1955
                                                        sep->user_data);
 
1956
 
 
1957
        avdtp_check_collision(session, AVDTP_ABORT, sep->stream);
1876
1958
 
1877
1959
        ret = avdtp_send(session, transaction, AVDTP_MSG_TYPE_ACCEPT,
1878
1960
                                                AVDTP_ABORT, NULL, 0);
1880
1962
                avdtp_sep_set_state(session, sep, AVDTP_STATE_ABORTING);
1881
1963
 
1882
1964
        return ret;
1883
 
 
1884
 
failed:
1885
 
        return avdtp_send(session, transaction, AVDTP_MSG_TYPE_REJECT,
1886
 
                                        AVDTP_ABORT, &err, sizeof(err));
1887
1965
}
1888
1966
 
1889
1967
static gboolean avdtp_secctl_cmd(struct avdtp *session, uint8_t transaction,
2166
2244
                if (session->streams && session->dc_timer)
2167
2245
                        remove_disconnect_timer(session);
2168
2246
 
 
2247
                if (session->req && session->req->collided) {
 
2248
                        DBG("Collision detected");
 
2249
                        goto next;
 
2250
                }
 
2251
 
2169
2252
                return TRUE;
2170
2253
        }
2171
2254
 
2216
2299
                break;
2217
2300
        }
2218
2301
 
 
2302
next:
2219
2303
        pending_req_free(session->req);
2220
2304
        session->req = NULL;
2221
2305
 
3574
3658
        if (stream->lsep->state != AVDTP_STATE_OPEN)
3575
3659
                return -EINVAL;
3576
3660
 
 
3661
        /* Recommendation 12:
 
3662
         *  If the RD has configured and opened a stream it is also responsible
 
3663
         *  to start the streaming via GAVDP_START.
 
3664
         */
 
3665
        if (stream->open_acp) {
 
3666
                stream->starting = TRUE;
 
3667
                return 0;
 
3668
        }
 
3669
 
3577
3670
        if (stream->close_int == TRUE) {
3578
3671
                error("avdtp_start: rejecting start since close is initiated");
3579
3672
                return -EINVAL;
3581
3674
 
3582
3675
        if (stream->starting == TRUE) {
3583
3676
                DBG("stream already started");
3584
 
                return -EINVAL;
 
3677
                return -EINPROGRESS;
3585
3678
        }
3586
3679
 
3587
3680
        memset(&req, 0, sizeof(req));