1 /** @file
2  *  @brief Bluetooth Microphone Control Profile (MICP) Microphone Device role.
3  *
4  *  Copyright (c) 2020 Bose Corporation
5  *  Copyright (c) 2020-2022 Nordic Semiconductor ASA
6  *  Copyright (c) 2022 Codecoup
7  *
8  *  SPDX-License-Identifier: Apache-2.0
9  */
10 
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <string.h>
14 
15 #include <zephyr/bluetooth/audio/aics.h>
16 #include <zephyr/bluetooth/conn.h>
17 #include <zephyr/bluetooth/audio/micp.h>
18 #include <zephyr/kernel.h>
19 #include <zephyr/sys/printk.h>
20 #include <zephyr/sys/util.h>
21 
micp_mic_dev_mute_cb(uint8_t mute)22 static void micp_mic_dev_mute_cb(uint8_t mute)
23 {
24 	printk("Mute value %u\n", mute);
25 }
26 
27 static struct bt_micp_mic_dev_cb micp_mic_dev_cbs = {
28 	.mute = micp_mic_dev_mute_cb,
29 };
30 
31 #if defined(CONFIG_BT_MICP_MIC_DEV_AICS)
32 static struct bt_micp_included micp_included;
33 
micp_mic_dev_aics_state_cb(struct bt_aics * inst,int err,int8_t gain,uint8_t mute,uint8_t mode)34 static void micp_mic_dev_aics_state_cb(struct bt_aics *inst, int err, int8_t gain, uint8_t mute,
35 				       uint8_t mode)
36 {
37 	if (err != 0) {
38 		printk("AICS state get failed (%d) for inst %p\n", err, inst);
39 	} else {
40 		printk("AICS inst %p state gain %d, mute %u, mode %u\n",
41 		       inst, gain, mute, mode);
42 	}
43 
44 }
micp_mic_dev_aics_gain_setting_cb(struct bt_aics * inst,int err,uint8_t units,int8_t minimum,int8_t maximum)45 static void micp_mic_dev_aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units,
46 					      int8_t minimum, int8_t maximum)
47 {
48 	if (err != 0) {
49 		printk("AICS gain settings get failed (%d) for inst %p\n", err, inst);
50 	} else {
51 		printk("AICS inst %p gain settings units %u, min %d, max %d\n",
52 		       inst, units, minimum, maximum);
53 	}
54 
55 }
micp_mic_dev_aics_input_type_cb(struct bt_aics * inst,int err,uint8_t input_type)56 static void micp_mic_dev_aics_input_type_cb(struct bt_aics *inst, int err, uint8_t input_type)
57 {
58 	if (err != 0) {
59 		printk("AICS input type get failed (%d) for inst %p\n", err, inst);
60 	} else {
61 		printk("AICS inst %p input type %u\n", inst, input_type);
62 	}
63 
64 }
micp_mic_dev_aics_status_cb(struct bt_aics * inst,int err,bool active)65 static void micp_mic_dev_aics_status_cb(struct bt_aics *inst, int err, bool active)
66 {
67 	if (err != 0) {
68 		printk("AICS status get failed (%d) for inst %p\n", err, inst);
69 	} else {
70 		printk("AICS inst %p status %s\n", inst, active ? "active" : "inactive");
71 	}
72 
73 }
micp_mic_dev_aics_description_cb(struct bt_aics * inst,int err,char * description)74 static void micp_mic_dev_aics_description_cb(struct bt_aics *inst, int err, char *description)
75 {
76 	if (err != 0) {
77 		printk("AICS description get failed (%d) for inst %p\n", err, inst);
78 	} else {
79 		printk("AICS inst %p description %s\n", inst, description);
80 	}
81 }
82 
83 static struct bt_aics_cb aics_cb = {
84 	.state = micp_mic_dev_aics_state_cb,
85 	.gain_setting = micp_mic_dev_aics_gain_setting_cb,
86 	.type = micp_mic_dev_aics_input_type_cb,
87 	.status = micp_mic_dev_aics_status_cb,
88 	.description = micp_mic_dev_aics_description_cb,
89 };
90 #endif /* CONFIG_BT_MICP_MIC_DEV_AICS */
91 
micp_mic_dev_init(void)92 int micp_mic_dev_init(void)
93 {
94 	int err;
95 	struct bt_micp_mic_dev_register_param micp_param;
96 
97 	(void)memset(&micp_param, 0, sizeof(micp_param));
98 
99 #if defined(CONFIG_BT_MICP_MIC_DEV_AICS)
100 	char input_desc[CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT][16];
101 
102 	for (int i = 0; i < ARRAY_SIZE(micp_param.aics_param); i++) {
103 		micp_param.aics_param[i].desc_writable = true;
104 		snprintf(input_desc[i], sizeof(input_desc[i]), "Input %d", i + 1);
105 		micp_param.aics_param[i].description = input_desc[i];
106 		micp_param.aics_param[i].type = BT_AICS_INPUT_TYPE_UNSPECIFIED;
107 		micp_param.aics_param[i].status = true;
108 		micp_param.aics_param[i].gain_mode = BT_AICS_MODE_MANUAL;
109 		micp_param.aics_param[i].units = 1;
110 		micp_param.aics_param[i].min_gain = -100;
111 		micp_param.aics_param[i].max_gain = 100;
112 		micp_param.aics_param[i].cb = &aics_cb;
113 	}
114 #endif /* CONFIG_BT_MICP_MIC_DEV_AICS */
115 
116 	micp_param.cb = &micp_mic_dev_cbs;
117 
118 	err = bt_micp_mic_dev_register(&micp_param);
119 	if (err != 0) {
120 		return err;
121 	}
122 
123 #if defined(CONFIG_BT_MICP_MIC_DEV_AICS)
124 	err = bt_micp_mic_dev_included_get(&micp_included);
125 	if (err != 0) {
126 		return err;
127 	}
128 #endif /* CONFIG_BT_MICP_MIC_DEV_AICS */
129 
130 	return 0;
131 }
132