diff --git a/src/rfcomm.c b/src/rfcomm.c
|
index 86c0d4d..00dd9ab 100644
|
--- a/src/rfcomm.c
|
+++ b/src/rfcomm.c
|
@@ -417,23 +417,39 @@ static int rfcomm_handler_bcs_set_cb(struct rfcomm_conn *c, const struct bt_at *
|
|
static int rfcomm_handler_resp_bcs_ok_cb(struct rfcomm_conn *c, const struct bt_at *at) {
|
struct ba_transport * const t = c->t;
|
- struct ba_transport *t_sco;
|
- struct bt_voice voice = {
|
- .setting = BT_VOICE_CVSD_16BIT,
|
+
|
+ /* XXX: this param should be read from rtl8xxx_config */
|
+ struct pcmif_param {
|
+ uint8_t pcmifctrl1[2];
|
+ uint8_t pcmifctrl2[2];
|
+ uint8_t pcmifctrl3[2];
|
+ uint8_t pcmconv;
|
+ uint8_t scoconv;
|
+ uint8_t hci_ext_codec;
|
+ } pcmif = {
|
+ 0x83, 0x10,
|
+ 0x00, 0x00,
|
+ 0x12, 0x80,
|
+ 0x00,
|
+ 0x00,
|
+ 0x01
|
};
|
|
if (rfcomm_handler_resp_ok_cb(c, at) != 0)
|
return -1;
|
|
- /* Change voice setting according to codec */
|
- if (t->rfcomm.sco->codec == HFP_CODEC_MSBC)
|
- voice.setting = BT_VOICE_TRANSPARENT;
|
- t_sco = t->rfcomm.sco;
|
- if (setsockopt(t_sco->sco.listen_fd, SOL_BLUETOOTH, BT_VOICE,
|
- &voice, sizeof(voice)) == -1) {
|
- error("setsockopt BT_VOICE error %d, %s", errno,
|
- strerror(errno));
|
- return 0;
|
+ if (t->rfcomm.sco->codec == HFP_CODEC_MSBC) {
|
+ pcmif.hci_ext_codec = 0x41;
|
+ pcmif.pcmifctrl3[1] = 0x04;
|
+ } else if (t->rfcomm.sco->codec == HFP_CODEC_CVSD) {
|
+ pcmif.hci_ext_codec = 0x01;
|
+ pcmif.pcmifctrl3[1] = 0x80;
|
+ }
|
+
|
+ if (hci_submit_cmd_wait(0x3f, 0x93, (uint8_t *)&pcmif,
|
+ sizeof(pcmif)) < 0) {
|
+ error("Couldn't set controller pcm interface");
|
+ return -1;
|
}
|
|
/* When codec selection is completed, notify connected clients, that
|
@@ -451,8 +467,24 @@ static int rfcomm_handler_bcs_resp_cb(struct rfcomm_conn *c, const struct bt_at
|
AT_TYPE_RESP, "", rfcomm_handler_resp_bcs_ok_cb };
|
struct ba_transport * const t = c->t;
|
const int fd = t->bt_fd;
|
+ struct ba_transport *t_sco;
|
+ struct bt_voice voice = {
|
+ .setting = BT_VOICE_CVSD_16BIT,
|
+ };
|
|
t->rfcomm.sco->codec = atoi(at->value);
|
+
|
+ /* Change voice setting according to codec */
|
+ if (t->rfcomm.sco->codec == HFP_CODEC_MSBC)
|
+ voice.setting = 0x0063;
|
+ t_sco = t->rfcomm.sco;
|
+ if (setsockopt(t_sco->sco.listen_fd, SOL_BLUETOOTH, BT_VOICE,
|
+ &voice, sizeof(voice)) == -1) {
|
+ error("setsockopt BT_VOICE error %d, %s", errno,
|
+ strerror(errno));
|
+ return 0;
|
+ }
|
+
|
if (rfcomm_write_at(fd, AT_TYPE_CMD_SET, "+BCS", at->value) == -1)
|
return -1;
|
|
@@ -679,7 +711,7 @@ void *rfcomm_thread(void *arg) {
|
case HFP_SLC_BRSF_SET_OK:
|
if (t->rfcomm.hfp_features & HFP_AG_FEAT_CODEC) {
|
/* XXX: If mSBC is supported, please change 1 to 1,2 */
|
- if (rfcomm_write_at(pfds[1].fd, AT_TYPE_CMD_SET, "+BAC", "1") == -1)
|
+ if (rfcomm_write_at(pfds[1].fd, AT_TYPE_CMD_SET, "+BAC", "1,2") == -1)
|
goto ioerror;
|
conn.handler = &rfcomm_handler_resp_ok;
|
break;
|
diff --git a/src/utils.c b/src/utils.c
|
index 70d069e..6b36829 100644
|
--- a/src/utils.c
|
+++ b/src/utils.c
|
@@ -138,6 +138,42 @@ fail:
|
return -1;
|
}
|
|
+int hci_submit_cmd_wait(uint16_t ogf, uint16_t ocf, uint8_t *params,
|
+ uint8_t plen)
|
+{
|
+ int fd;
|
+ uint16_t index = 0;
|
+ uint8_t status;
|
+ int ret;
|
+ struct hci_request rq;
|
+
|
+ fd = hci_open_dev(index);
|
+ if (fd < 0) {
|
+ error("Couldn't open device: %s(%d)\n", strerror(errno), errno);
|
+ return -1;
|
+ }
|
+
|
+ memset(&rq, 0, sizeof(rq));
|
+ rq.ogf = ogf;
|
+ rq.ocf = ocf;
|
+ rq.cparam = params;
|
+ rq.clen = plen;
|
+ rq.rparam = &status;
|
+ rq.rlen = 1;
|
+
|
+ ret = hci_send_req(fd, &rq, 1000);
|
+ if (status || ret < 0) {
|
+ error("Can't send cmd for hci%d: %s (%d)\n", index,
|
+ strerror(errno), errno);
|
+ hci_close_dev(fd);
|
+ return -1;
|
+ }
|
+
|
+ hci_close_dev(fd);
|
+
|
+ return 0;
|
+}
|
+
|
/**
|
* Get BlueZ D-Bus object path for given profile and codec.
|
*
|
diff --git a/src/utils.h b/src/utils.h
|
index a15625f..46da2eb 100644
|
--- a/src/utils.h
|
+++ b/src/utils.h
|
@@ -28,6 +28,8 @@ int a2dp_sbc_default_bitpool(int freq, int mode);
|
|
int hci_devlist(struct hci_dev_info **di, int *num);
|
int hci_open_sco(const struct hci_dev_info *di, const bdaddr_t *ba, bool transparent);
|
+int hci_submit_cmd_wait(uint16_t ogf, uint16_t ocf, uint8_t *params,
|
+ uint8_t plen);
|
|
const char *bluetooth_profile_to_string(enum bluetooth_profile profile);
|
const char *bluetooth_a2dp_codec_to_string(uint16_t codec);
|
--
|
2.17.1
|