diff options
author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2007-06-14 20:36:26 +0000 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2007-06-14 20:36:26 +0000 |
commit | 5ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5 (patch) | |
tree | b158176d2c90868417f8611f0491a14ce5726ad2 /audio/ctl_bluetooth.c | |
parent | 9d1a7f6c590fc40315f74e710e88bcda85d7f7ba (diff) |
Initial support for audio control plugin and some code cleanups.
Diffstat (limited to 'audio/ctl_bluetooth.c')
-rw-r--r-- | audio/ctl_bluetooth.c | 222 |
1 files changed, 158 insertions, 64 deletions
diff --git a/audio/ctl_bluetooth.c b/audio/ctl_bluetooth.c index 4d73c788..411d7e00 100644 --- a/audio/ctl_bluetooth.c +++ b/audio/ctl_bluetooth.c @@ -33,7 +33,11 @@ #include "ipc.h" +#ifdef ENABLE_DEBUG #define DBG(fmt, arg...) printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg) +#else +#define DBG(fmt, arg...) +#endif #define BLUETOOTH_MINVOL 0 #define BLUETOOTH_MAXVOL 15 @@ -53,15 +57,24 @@ static const char *vol_devices[2] = { [BLUETOOTH_CAPTURE] = "Capture volume", }; +static void bluetooth_exit(struct bluetooth_data *data) +{ + if (data == NULL) + return; + + if (data->sock >= 0) + close(data->sock); + + free(data); +} + static void bluetooth_close(snd_ctl_ext_t *ext) { struct bluetooth_data *data = ext->private_data; DBG("ext %p", ext); - close(data->sock); - - free(data); + bluetooth_exit(data); } static int bluetooth_elem_count(snd_ctl_ext_t *ext) @@ -125,48 +138,140 @@ static int bluetooth_get_integer_info(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, return 0; } +static int bluetooth_send_ctl(struct bluetooth_data *data, + struct ipc_packet *pkt, int len) +{ + int ret; + + ret = send(data->sock, pkt, len, MSG_NOSIGNAL); + if (ret <= 0) { + SYSERR("Unable to request new volume value to server"); + return -errno; + } + + ret = recv(data->sock, pkt, len, 0); + if (ret <= 0) { + SYSERR("Unable to receive new volume value from server"); + return -errno; + } + + if(pkt->type != PKT_TYPE_CTL_RSP) { + SNDERR("Unexpected packet type %d received", pkt->type); + return -EINVAL; + } + + if(pkt->length != sizeof(struct ipc_data_ctl)) { + SNDERR("Unexpected packet length %d received", pkt->length); + return -EINVAL; + } + + return 0; +} + static int bluetooth_read_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *value) { struct bluetooth_data *data = ext->private_data; - unsigned char buf[] = { 0x00, 0x00 }; - int len; + struct ipc_packet *pkt; + struct ipc_data_ctl *ctl; + int len, ret; DBG("ext %p key %ld", ext, key); - len = write(data->sock, buf, sizeof(buf)); - + len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_ctl); + pkt = malloc(len); + memset(pkt, 0, len); *value = 0; - return 0; + pkt->type = PKT_TYPE_CTL_REQ; + pkt->length = sizeof(struct ipc_data_ctl); + ctl = (struct ipc_data_ctl *) pkt->data; + ctl->mode = key; + + if ((ret = bluetooth_send_ctl(data, pkt, len)) < 0) + goto done; + + *value = ctl->key; +done: + free(pkt); + return ret; } static int bluetooth_write_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *value) { struct bluetooth_data *data = ext->private_data; - unsigned char buf[] = { 0xff, 0xff }; - int len; + struct ipc_packet *pkt; + struct ipc_data_ctl *ctl; + long current; + int len, ret; DBG("ext %p key %ld", ext, key); - len = write(data->sock, buf, sizeof(buf)); + if ((ret = bluetooth_read_integer(ext, key, ¤t)) < 0) + return ret; - return 0; + if (*value == current) + return 0; + + len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_ctl); + pkt = malloc(len); + memset(pkt, 0, len); + + pkt->length = sizeof(struct ipc_data_ctl); + ctl = (struct ipc_data_ctl *) pkt->data; + ctl->mode = key; + + while (*value != current) { + pkt->type = PKT_TYPE_CTL_REQ; + ctl->key = (*value > current) ? CTL_KEY_VOL_UP : CTL_KEY_VOL_DOWN; + + if ((ret = bluetooth_send_ctl(data, pkt, len)) < 0) + break; + + current = ctl->key; + } + + free(pkt); + return ret; } static int bluetooth_read_event(snd_ctl_ext_t *ext, snd_ctl_elem_id_t *id, unsigned int *event_mask) { struct bluetooth_data *data = ext->private_data; - unsigned char buf[128]; - int len; + struct ipc_packet *pkt; + struct ipc_data_ctl *ctl; + int len, ret; - //DBG("ext %p id %p", ext, id); + DBG("ext %p id %p", ext, id); - len = recv(data->sock, buf, sizeof(buf), MSG_DONTWAIT); + len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_ctl); + pkt = malloc(len); + memset(pkt, 0, len); - return 0; + ret = recv(data->sock, pkt, len, MSG_DONTWAIT); + if (ret <= 0) + return -errno; + + if(pkt->type != PKT_TYPE_CTL_NTFY) { + SNDERR("Unexpected packet type %d received!", pkt->type); + return -EAGAIN; + } + + if(pkt->length != sizeof(struct ipc_data_ctl)) { + SNDERR("Unexpected packet length %d received", pkt->length); + return -EAGAIN; + } + + ctl = (struct ipc_data_ctl *) pkt->data; + snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_id_set_name(id, ctl->mode == BLUETOOTH_PLAYBACK ? + vol_devices[BLUETOOTH_PLAYBACK] : + vol_devices[BLUETOOTH_CAPTURE]); + *event_mask = SND_CTL_EVENT_MASK_VALUE; + + return 1; } static snd_ctl_ext_callback_t bluetooth_callback = { @@ -181,69 +286,60 @@ static snd_ctl_ext_callback_t bluetooth_callback = { .read_event = bluetooth_read_event, }; -SND_CTL_PLUGIN_DEFINE_FUNC(bluetooth) +static int bluetooth_init(struct bluetooth_data *data) { - snd_config_iterator_t iter, next; - struct bluetooth_data *data; - struct sockaddr_un addr; - unsigned int id; - int sk, err; - - DBG("Bluetooth Control plugin"); - - snd_config_for_each(iter, next, conf) { - snd_config_t *n = snd_config_iterator_entry(iter); - const char *id; - - if (snd_config_get_id(n, &id) < 0) - continue; + int sk, err, id; + struct sockaddr_un addr = { + AF_UNIX, IPC_SOCKET_NAME + }; - if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0) - continue; + if (!data) + return -EINVAL; - SNDERR("Unknown field %s", id); + memset(data, 0, sizeof(struct bluetooth_data)); - return -EINVAL; - } + data->sock = -1; id = abs(getpid() * rand()); - sk = socket(PF_LOCAL, SOCK_DGRAM, 0); - if (sk < 0) { + if ((sk = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { + err = -errno; SNDERR("Can't open socket"); return -errno; } - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path + 1, UNIX_PATH_MAX - 2, "%s/%d", - IPC_SOCKET_NAME, id); - - if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - SNDERR("Can't bind socket"); - close(sk); - return -errno; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path + 1, UNIX_PATH_MAX - 2, "%s", IPC_SOCKET_NAME); - + DBG("Connecting to address: %s", addr.sun_path + 1); if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + err = -errno; SNDERR("Can't connect socket"); close(sk); - return -errno; + return err; } - data = malloc(sizeof(*data)); + data->sock = sk; + + return 0; +} + +SND_CTL_PLUGIN_DEFINE_FUNC(bluetooth) +{ + struct bluetooth_data *data; + int err; + + DBG("Bluetooth Control plugin"); + + data = malloc(sizeof(struct bluetooth_data)); + memset(data, 0, sizeof(struct bluetooth_data)); if (!data) { - close(sk); - return -ENOMEM; + err = -ENOMEM; + goto error; } - memset(data, 0, sizeof(*data)); + err = bluetooth_init(data); + if (err < 0) + goto error; - data->sock = sk; + memset(data, 0, sizeof(*data)); data->ext.version = SND_CTL_EXT_VERSION; data->ext.card_idx = -1; @@ -255,7 +351,7 @@ SND_CTL_PLUGIN_DEFINE_FUNC(bluetooth) strncpy(data->ext.mixername, "Bluetooth Audio", sizeof(data->ext.mixername) - 1); data->ext.callback = &bluetooth_callback; - data->ext.poll_fd = sk; + data->ext.poll_fd = data->sock; data->ext.private_data = data; err = snd_ctl_ext_create(&data->ext, name, mode); @@ -267,9 +363,7 @@ SND_CTL_PLUGIN_DEFINE_FUNC(bluetooth) return 0; error: - close(sk); - - free(data); + bluetooth_exit(data); return err; } |