Skip to content

Commit 03ee85f

Browse files
committed
Bluetooth: Classic: HFP: AG: Add vendor at cmd API and callback.
bug: v/79377 Rootcause: Add vendor_at_cmd callback and bt_hfp_ag_send_vendor API to recieve and send vendor-specific AT commands. Signed-off-by: liyuheng [email protected]
1 parent 8db780e commit 03ee85f

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

include/zephyr/bluetooth/classic/hfp_ag.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,35 @@ struct bt_hfp_ag_cb {
460460
*/
461461
void (*hf_indicator_value)(struct bt_hfp_ag *ag, enum hfp_ag_hf_indicators indicator,
462462
uint32_t value);
463+
464+
/** Vendor specific / custom AT command callback
465+
*
466+
* If this callback is provided it will be called whenever an AT command
467+
* is received from the HF that is not recognized and handled by the
468+
* HFP AG stack.
469+
*
470+
* The @p cmd string contains the full AT command line as received on
471+
* the RFCOMM link, without the terminating carriage return character.
472+
* Example: "AT+XMI=1,2".
473+
*
474+
* The return value controls how the HFP AG core replies:
475+
* - ret < 0 : The command is rejected and the core will send the
476+
* standard "ERROR" or "+CME ERROR:<code>" depending on
477+
* the CMEE setting.
478+
* - ret == 0: The command was handled successfully and the core will
479+
* send the standard "OK" final result code.
480+
* - ret > 0 : The application is responsible for sending all responses,
481+
* including the final "OK" / "ERROR" / "+CME ERROR:<code>",
482+
* by calling @ref bt_hfp_ag_send_vendor from an appropriate
483+
* context. The HFP AG core will NOT send any automatic
484+
* final result code in this case.
485+
*
486+
* @param ag HFP AG object.
487+
* @param cmd Zero-terminated AT command line without trailing <CR>.
488+
*
489+
* @return Application-defined result as described above.
490+
*/
491+
int (*vendor_at_cmd)(struct bt_hfp_ag *ag, const char *cmd);
463492
};
464493

465494
/** @brief Register HFP AG profile
@@ -819,6 +848,26 @@ int Z_API(bt_hfp_ag_battery_level)(struct bt_hfp_ag *ag, uint8_t level);
819848
*/
820849
int Z_API(bt_hfp_ag_service_availability)(struct bt_hfp_ag *ag, bool available);
821850

851+
/** @brief Send vendor specific / custom AT response from the AG
852+
*
853+
* Send a vendor specific or otherwise custom AT result or unsolicited
854+
* response line from the AG to the HF.
855+
* The given string is sent as-is and will be wrapped with the standard
856+
* "\r\n" prefix and suffix on the wire.
857+
*
858+
* Examples (rsp non-NULL):
859+
* - rsp == NULL -> sends a standard final result "OK"
860+
* (i.e. "\r\nOK\r\n").
861+
* - rsp = "+CUSTOM:0" -> sends "\r\n+CUSTOM:0\r\n"
862+
* - rsp = "+VENDOR:1" -> sends "\r\n+VENDOR:1\r\n"
863+
*
864+
* @param ag HFP AG object.
865+
* @param rsp AT response string without CR/LF terminators, or NULL to send "OK".
866+
*
867+
* @return 0 in case of success or negative value in case of error.
868+
*/
869+
int Z_API(bt_hfp_ag_send_vendor)(struct bt_hfp_ag *ag, const char *rsp);
870+
822871
/** @brief Activate/deactivate HF indicator
823872
*
824873
* It allows HF to issue the +BIND unsolicited result code to

subsys/bluetooth/host/classic/hfp_ag.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3523,6 +3523,23 @@ static void hfp_ag_recv(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
35233523
}
35243524
}
35253525

3526+
if ((err == -ENOEXEC) && bt_ag && bt_ag->vendor_at_cmd) {
3527+
size_t copy_len;
3528+
3529+
copy_len = MIN(len, sizeof(ag->buffer) - 1);
3530+
memcpy(ag->buffer, data, copy_len);
3531+
ag->buffer[copy_len] = '\0';
3532+
3533+
if ((copy_len > 0) && (ag->buffer[copy_len - 1] == '\r')) {
3534+
ag->buffer[copy_len - 1] = '\0';
3535+
}
3536+
3537+
err = bt_ag->vendor_at_cmd(ag, ag->buffer);
3538+
if (err > 0) {
3539+
return;
3540+
}
3541+
}
3542+
35263543
if (err == -EINPROGRESS) {
35273544
LOG_DBG("OK code will be replied later");
35283545
return;
@@ -5212,6 +5229,34 @@ int Z_API(bt_hfp_ag_service_availability)(struct bt_hfp_ag *ag, bool available)
52125229
return err;
52135230
}
52145231

5232+
int Z_API(bt_hfp_ag_send_vendor)(struct bt_hfp_ag *ag, const char *rsp)
5233+
{
5234+
int err;
5235+
const char *line;
5236+
5237+
LOG_DBG("");
5238+
5239+
if (ag == NULL) {
5240+
return -EINVAL;
5241+
}
5242+
5243+
hfp_ag_lock(ag);
5244+
if (ag->state != BT_HFP_CONNECTED) {
5245+
hfp_ag_unlock(ag);
5246+
return -ENOTCONN;
5247+
}
5248+
hfp_ag_unlock(ag);
5249+
5250+
line = (rsp == NULL) ? "OK" : rsp;
5251+
5252+
err = hfp_ag_send_data(ag, NULL, NULL, "\r\n%s\r\n", line);
5253+
if (err) {
5254+
LOG_ERR("Fail to send vendor specific response (%d)", err);
5255+
}
5256+
5257+
return err;
5258+
}
5259+
52155260
int Z_API(bt_hfp_ag_hf_indicator)(struct bt_hfp_ag *ag, enum hfp_ag_hf_indicators indicator, bool enable)
52165261
{
52175262
#if defined(CONFIG_BT_HFP_AG_HF_INDICATORS)

0 commit comments

Comments
 (0)