OSDN Git Service

auto import from //branches/cupcake_rel/...@140373
authorThe Android Open Source Project <initial-contribution@android.com>
Thu, 19 Mar 2009 00:39:43 +0000 (17:39 -0700)
committerThe Android Open Source Project <initial-contribution@android.com>
Thu, 19 Mar 2009 00:39:43 +0000 (17:39 -0700)
utils/audio/Android.mk
utils/audio/audio-api.txt
utils/audio/avdtp.c
utils/audio/control.c
utils/audio/device.c
utils/audio/liba2dp.c

index 309cfa7..c0b4d10 100644 (file)
@@ -43,7 +43,9 @@ LOCAL_MODULE := audio
 
 include $(BUILD_SHARED_LIBRARY)
 
-# liba2sp
+#
+# liba2dp
+# This is linked to Audioflinger so **LGPL only**
 
 include $(CLEAR_VARS)
 
@@ -53,23 +55,13 @@ LOCAL_SRC_FILES:= \
        ../sbc/sbc.c.arm \
        ../sbc/sbc_primitives.c
 
-# to improve SBC performance   
+# to improve SBC performance
 LOCAL_CFLAGS:= -funroll-loops
 
 LOCAL_C_INCLUDES:= \
-       $(call include-path-for, bluez-libs) \
-       $(call include-path-for, bluez-utils)/common \
-       $(call include-path-for, bluez-utils)/hcid \
-       $(call include-path-for, bluez-utils)/sdpd \
-       $(call include-path-for, bluez-utils)/eglib \
-       $(call include-path-for, bluez-utils)/gdbus \
        $(call include-path-for, bluez-utils)/sbc \
-       $(call include-path-for, dbus)
 
 LOCAL_SHARED_LIBRARIES := \
-       libbluetooth \
-       libhcid \
-       libdbus \
        libcutils
 
 LOCAL_MODULE := liba2dp
index cba2069..288e639 100644 (file)
@@ -302,6 +302,20 @@ Methods            boolean IsConnected()
 
                        Returns TRUE if AVRCP is connected.
 
+               void Connect()
+
+                       Connect to AVRCP on the remote device.
+
+                       NOTE: Most remote devices do not allow AVRCP without
+                       A2DP, so this is intended for testing purposes.
+
+               void Disconnect()
+
+                       Disconnect from the remote device.
+
+                       NOTE: Most remote devices do not allow AVRCP without
+                       A2DP, so this is intended for testing purposes.
+
 Signals                void Connected()
 
                        Sent when a successful AVRCP connection has been made.
index 3a8060f..5e74b7e 100644 (file)
@@ -73,6 +73,7 @@
 #define AVDTP_PKT_TYPE_END                     0x03
 
 #define AVDTP_MSG_TYPE_COMMAND                 0x00
+#define AVDTP_MSG_TYPE_GENERAL_REJECT          0x01
 #define AVDTP_MSG_TYPE_ACCEPT                  0x02
 #define AVDTP_MSG_TYPE_REJECT                  0x03
 
@@ -1043,8 +1044,8 @@ static GSList *caps_to_list(uint8_t *data, int size,
 static gboolean avdtp_unknown_cmd(struct avdtp *session, uint8_t transaction,
                                                        void *buf, int size)
 {
-       return avdtp_send(session, transaction, AVDTP_MSG_TYPE_REJECT,
-                                                               0, NULL, 0);
+       return avdtp_send(session, transaction, AVDTP_MSG_TYPE_GENERAL_REJECT,
+                                                               session->in.signal_id, NULL, 0);
 }
 
 static gboolean avdtp_discover_cmd(struct avdtp *session, uint8_t transaction,
@@ -1078,8 +1079,8 @@ static gboolean avdtp_getcap_cmd(struct avdtp *session, uint8_t transaction,
        uint8_t err, buf[1024], *ptr = buf;
 
        if (size < sizeof(struct seid_req)) {
-               error("Too short getcap request");
-               return FALSE;
+               err = AVDTP_BAD_LENGTH;
+               goto failed;
        }
 
        sep = find_local_sep_by_seid(req->acp_seid);
@@ -1122,6 +1123,7 @@ static gboolean avdtp_setconf_cmd(struct avdtp *session, uint8_t transaction,
        struct avdtp_local_sep *sep;
        struct avdtp_stream *stream;
        uint8_t err, category = 0x00;
+       GSList *l;
 
        if (size < sizeof(struct setconf_req)) {
                error("Too short getcap request");
@@ -1148,6 +1150,16 @@ static gboolean avdtp_setconf_cmd(struct avdtp *session, uint8_t transaction,
                                        &stream->codec);
        stream->sock = -1;
 
+       /* Verify that the Media Transport capability's length = 0. Reject otherwise */
+       for (l = stream->caps; l != NULL; l = g_slist_next(l)) {
+               struct avdtp_service_capability *cap = l->data;
+
+               if ((cap->category == AVDTP_MEDIA_TRANSPORT) && (cap->length != 0)) {
+                       err = AVDTP_BAD_MEDIA_TRANSPORT_FORMAT;
+                       goto failed;
+               }
+       }
+
        if (sep->ind && sep->ind->set_configuration) {
                if (!sep->ind->set_configuration(session, sep, stream,
                                                        stream->caps, &err,
@@ -1181,7 +1193,47 @@ failed:
 static gboolean avdtp_getconf_cmd(struct avdtp *session, uint8_t transaction,
                                        struct seid_req *req, int size)
 {
-       return avdtp_unknown_cmd(session, transaction, (void *) req, size);
+       GSList *l;
+       struct avdtp_local_sep *sep = NULL;
+       int rsp_size;
+       uint8_t err;
+       uint8_t buf[1024];
+       uint8_t *ptr = buf;
+
+       if (size < sizeof(struct seid_req)) {
+               error("Too short getconf request");
+               return FALSE;
+       }
+
+       memset(buf, 0, sizeof(buf));
+
+       sep = find_local_sep_by_seid(req->acp_seid);
+       if (!sep) {
+               err = AVDTP_BAD_ACP_SEID;
+               goto failed;
+       }
+       if (!sep->stream || !sep->stream->caps) {
+               err = AVDTP_UNSUPPORTED_CONFIGURATION;
+               goto failed;
+       }
+
+       for (l = sep->stream->caps, rsp_size = 0; l != NULL; l = g_slist_next(l)) {
+               struct avdtp_service_capability *cap = l->data;
+
+               if (rsp_size + cap->length + 2 > sizeof(buf))
+                       break;
+
+               memcpy(ptr, cap, cap->length + 2);
+               rsp_size += cap->length + 2;
+               ptr += cap->length + 2;
+       }
+
+       return avdtp_send(session, transaction, AVDTP_MSG_TYPE_ACCEPT,
+                               AVDTP_GET_CONFIGURATION, buf, rsp_size);
+
+failed:
+       return avdtp_send(session, transaction, AVDTP_MSG_TYPE_REJECT,
+                               AVDTP_GET_CONFIGURATION, &err, sizeof(err));
 }
 
 static gboolean avdtp_reconf_cmd(struct avdtp *session, uint8_t transaction,
index 267b135..e638691 100644 (file)
@@ -71,7 +71,9 @@
 /* ctype entries */
 #define CTYPE_CONTROL          0x0
 #define CTYPE_STATUS           0x1
+#define CTYPE_NOT_IMPLEMENTED  0x8
 #define CTYPE_ACCEPTED         0x9
+#define CTYPE_REJECTED         0xA
 #define CTYPE_STABLE           0xC
 
 /* opcodes */
@@ -494,21 +496,21 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
                        avrcp->code, avrcp->subunit_type, avrcp->subunit_id,
                        avrcp->opcode, operand_count);
 
-       if (avctp->packet_type == AVCTP_PACKET_SINGLE &&
-                       avctp->cr == AVCTP_COMMAND &&
-                       avctp->pid == htons(AV_REMOTE_SVCLASS_ID) &&
+       if (avctp->packet_type != AVCTP_PACKET_SINGLE) {
+               avctp->cr = AVCTP_RESPONSE;
+               avrcp->code = CTYPE_NOT_IMPLEMENTED;
+       } else if (avctp->pid != htons(AV_REMOTE_SVCLASS_ID)) {
+               avctp->ipid = 1;
+               avctp->cr = AVCTP_RESPONSE;
+               avrcp->code = CTYPE_REJECTED;
+       } else if (avctp->cr == AVCTP_COMMAND &&
                        avrcp->code == CTYPE_CONTROL &&
                        avrcp->subunit_type == SUBUNIT_PANEL &&
                        avrcp->opcode == OP_PASSTHROUGH) {
                handle_panel_passthrough(session, operands, operand_count);
                avctp->cr = AVCTP_RESPONSE;
                avrcp->code = CTYPE_ACCEPTED;
-               ret = write(session->sock, buf, packet_size);
-       }
-
-       if (avctp->packet_type == AVCTP_PACKET_SINGLE &&
-                       avctp->cr == AVCTP_COMMAND &&
-                       avctp->pid == htons(AV_REMOTE_SVCLASS_ID) &&
+       } else if (avctp->cr == AVCTP_COMMAND &&
                        avrcp->code == CTYPE_STATUS &&
                        (avrcp->opcode == OP_UNITINFO
                        || avrcp->opcode == OP_SUBUNITINFO)) {
@@ -516,8 +518,11 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
                avrcp->code = CTYPE_STABLE;
                debug("reply to %s", avrcp->opcode == OP_UNITINFO ?
                                "OP_UNITINFO" : "OP_SUBUNITINFO");
-               ret = write(session->sock, buf, packet_size);
+       } else {
+               avctp->cr = AVCTP_RESPONSE;
+               avrcp->code = CTYPE_REJECTED;
        }
+       ret = write(session->sock, buf, packet_size);
 
        return TRUE;
 
@@ -935,6 +940,40 @@ void avrcp_exit(void)
        connection = NULL;
 }
 
+static DBusMessage *control_connect(DBusConnection *conn, DBusMessage *msg,
+                                       void *data)
+{
+       struct audio_device *device = data;
+       DBusMessage *reply;
+       dbus_bool_t result;
+
+       reply = dbus_message_new_method_return(msg);
+       if (!reply)
+               return NULL;
+
+       result = avrcp_connect(device);
+
+       dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &result,
+                                       DBUS_TYPE_INVALID);
+
+       return reply;
+}
+
+static DBusMessage *control_disconnect(DBusConnection *conn, DBusMessage *msg,
+                                       void *data)
+{
+       struct audio_device *device = data;
+       DBusMessage *reply;
+
+       reply = dbus_message_new_method_return(msg);
+       if (!reply)
+               return NULL;
+
+       avrcp_disconnect(device);
+
+       return reply;
+}
+
 static DBusMessage *control_is_connected(DBusConnection *conn,
                                                DBusMessage *msg,
                                                void *data)
@@ -957,6 +996,8 @@ static DBusMessage *control_is_connected(DBusConnection *conn,
 }
 
 static GDBusMethodTable control_methods[] = {
+       { "Connect",            "",     "b",    control_connect},
+       { "Disconnect",         "",     "",     control_disconnect},
        { "IsConnected",        "",     "b",    control_is_connected },
        { NULL, NULL, NULL, NULL }
 };
index e38e734..2f9e1fb 100644 (file)
@@ -466,7 +466,7 @@ gboolean device_is_connected(struct audio_device *dev, const char *interface)
        else if (!strcmp(interface, AUDIO_HEADSET_INTERFACE) && dev->headset &&
                        headset_is_active(dev))
                return TRUE;
-       else if (!strcmp(interface, AUDIO_CONTROL_INTERFACE) && dev->headset &&
+       else if (!strcmp(interface, AUDIO_CONTROL_INTERFACE) && dev->control &&
                        control_is_active(dev))
                return TRUE;
 
index 55627e3..01c08c2 100644 (file)
@@ -719,7 +719,7 @@ static int bluetooth_init(struct bluetooth_data *data)
        data->server.fd = sk;
        data->server.events = POLLIN;
 
-    return 0;
+       return 0;
 }
 
 static int bluetooth_configure(struct bluetooth_data *data)
@@ -816,7 +816,7 @@ int a2dp_write(a2dpData d, const void* buffer, int count)
 {
        struct bluetooth_data* data = (struct bluetooth_data*)d;
        uint8_t* src = (uint8_t *)buffer;
-       int codesize = data->codesize;
+       int codesize;
        int err, ret = 0;
        long frames_left = count;
        int encoded, written;
@@ -836,8 +836,8 @@ int a2dp_write(a2dpData d, const void* buffer, int count)
 
 configure:
        if (!data->configured) {
-       err = bluetooth_configure(data);
-       if (err < 0)
+               err = bluetooth_configure(data);
+               if (err < 0)
                        return err;
                did_configure = 1;
        }
@@ -853,6 +853,8 @@ configure:
                }
        }
 
+       codesize = data->codesize;
+
        while (frames_left >= codesize) {
                /* Enough data to encode (sbc wants 512 byte blocks) */
                encoded = sbc_encode(&(data->sbc), src, codesize,