3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "src/shared/util.h"
35 #include "src/shared/ringbuf.h"
36 #include "src/shared/queue.h"
37 #include "src/shared/io.h"
38 #include "src/shared/hfp.h"
45 struct ringbuf *read_buf;
46 struct ringbuf *write_buf;
47 struct queue *cmd_handlers;
50 hfp_command_func_t command_callback;
51 hfp_destroy_func_t command_destroy;
53 hfp_debug_func_t debug_callback;
54 hfp_destroy_func_t debug_destroy;
57 hfp_disconnect_func_t disconnect_callback;
58 hfp_destroy_func_t disconnect_destroy;
59 void *disconnect_data;
70 struct ringbuf *read_buf;
71 struct ringbuf *write_buf;
74 struct queue *cmd_queue;
76 struct queue *event_handlers;
78 hfp_debug_func_t debug_callback;
79 hfp_destroy_func_t debug_destroy;
82 hfp_disconnect_func_t disconnect_callback;
83 hfp_destroy_func_t disconnect_destroy;
84 void *disconnect_data;
93 hfp_destroy_func_t destroy;
94 hfp_result_func_t callback;
102 struct cmd_response {
103 hfp_response_func_t resp_cb;
104 struct hfp_context *response;
109 struct event_handler {
112 hfp_destroy_func_t destroy;
113 hfp_hf_result_func_t callback;
116 static void destroy_cmd_handler(void *data)
118 struct cmd_handler *handler = data;
120 if (handler->destroy)
121 handler->destroy(handler->user_data);
123 free(handler->prefix);
128 static bool match_handler_prefix(const void *a, const void *b)
130 const struct cmd_handler *handler = a;
131 const char *prefix = b;
133 if (strcmp(handler->prefix, prefix) != 0)
139 static void write_watch_destroy(void *user_data)
141 struct hfp_gw *hfp = user_data;
143 hfp->writer_active = false;
146 static bool can_write_data(struct io *io, void *user_data)
148 struct hfp_gw *hfp = user_data;
149 ssize_t bytes_written;
151 bytes_written = ringbuf_write(hfp->write_buf, hfp->fd);
152 if (bytes_written < 0)
155 if (ringbuf_len(hfp->write_buf) > 0)
161 static void wakeup_writer(struct hfp_gw *hfp)
163 if (hfp->writer_active)
166 if (!ringbuf_len(hfp->write_buf))
169 if (!io_set_write_handler(hfp->io, can_write_data,
170 hfp, write_watch_destroy))
173 hfp->writer_active = true;
176 static void skip_whitespace(struct hfp_context *context)
178 while (context->data[context->offset] == ' ')
182 static void handle_unknown_at_command(struct hfp_gw *hfp,
185 if (hfp->command_callback) {
186 hfp->result_pending = true;
187 hfp->command_callback(data, hfp->command_data);
189 hfp_gw_send_result(hfp, HFP_RESULT_ERROR);
193 static bool handle_at_command(struct hfp_gw *hfp, const char *data)
195 struct cmd_handler *handler;
196 const char *separators = ";?=\0";
197 struct hfp_context context;
198 enum hfp_gw_cmd_type type;
199 char lookup_prefix[18];
200 uint8_t pref_len = 0;
207 skip_whitespace(&context);
209 if (strlen(data + context.offset) < 3)
212 if (strncmp(data + context.offset, "AT", 2))
213 if (strncmp(data + context.offset, "at", 2))
217 prefix = data + context.offset;
219 if (isalpha(prefix[0])) {
220 lookup_prefix[pref_len++] = toupper(prefix[0]);
222 pref_len = strcspn(prefix, separators);
223 if (pref_len > 17 || pref_len < 2)
226 for (i = 0; i < pref_len; i++)
227 lookup_prefix[i] = toupper(prefix[i]);
230 lookup_prefix[pref_len] = '\0';
231 context.offset += pref_len;
233 if (lookup_prefix[0] == 'D') {
234 type = HFP_GW_CMD_TYPE_SET;
238 if (data[context.offset] == '=') {
240 if (data[context.offset] == '?') {
242 type = HFP_GW_CMD_TYPE_TEST;
244 type = HFP_GW_CMD_TYPE_SET;
249 if (data[context.offset] == '?') {
251 type = HFP_GW_CMD_TYPE_READ;
255 type = HFP_GW_CMD_TYPE_COMMAND;
259 handler = queue_find(hfp->cmd_handlers, match_handler_prefix,
262 handle_unknown_at_command(hfp, data);
266 hfp->result_pending = true;
267 handler->callback(&context, type, handler->user_data);
272 static void next_field(struct hfp_context *context)
274 if (context->data[context->offset] == ',')
278 bool hfp_context_get_number_default(struct hfp_context *context,
280 unsigned int default_val)
282 skip_whitespace(context);
284 if (context->data[context->offset] == ',') {
292 return hfp_context_get_number(context, val);
295 bool hfp_context_get_number(struct hfp_context *context,
301 skip_whitespace(context);
305 while (context->data[i] >= '0' && context->data[i] <= '9')
306 tmp = tmp * 10 + context->data[i++] - '0';
308 if (i == context->offset)
315 skip_whitespace(context);
321 bool hfp_context_open_container(struct hfp_context *context)
323 skip_whitespace(context);
325 /* The list shall be preceded by a left parenthesis "(") */
326 if (context->data[context->offset] != '(')
334 bool hfp_context_close_container(struct hfp_context *context)
336 skip_whitespace(context);
338 /* The list shall be followed by a right parenthesis (")" V250 5.7.3.1*/
339 if (context->data[context->offset] != ')')
349 bool hfp_context_get_string(struct hfp_context *context, char *buf,
353 const char *data = context->data;
356 skip_whitespace(context);
358 if (data[context->offset] != '"')
361 offset = context->offset;
364 while (data[offset] != '\0' && data[offset] != '"') {
368 buf[i++] = data[offset];
377 if (data[offset] == '"')
382 context->offset = offset;
384 skip_whitespace(context);
390 bool hfp_context_get_unquoted_string(struct hfp_context *context,
391 char *buf, uint8_t len)
393 const char *data = context->data;
398 skip_whitespace(context);
400 c = data[context->offset];
401 if (c == '"' || c == ')' || c == '(')
404 offset = context->offset;
406 while (data[offset] != '\0' && data[offset] != ',' &&
407 data[offset] != ')') {
411 buf[i++] = data[offset];
420 context->offset = offset;
427 bool hfp_context_has_next(struct hfp_context *context)
429 return context->data[context->offset] != '\0';
432 void hfp_context_skip_field(struct hfp_context *context)
434 const char *data = context->data;
435 unsigned int offset = context->offset;
437 while (data[offset] != '\0' && data[offset] != ',')
440 context->offset = offset;
444 bool hfp_context_get_range(struct hfp_context *context, uint32_t *min,
450 start = context->offset;
452 if (!hfp_context_get_number(context, &l))
455 if (context->data[context->offset] != '-')
460 if (!hfp_context_get_number(context, &h))
471 context->offset = start;
475 static void process_input(struct hfp_gw *hfp)
479 bool free_ptr = false;
483 str = ringbuf_peek(hfp->read_buf, 0, &len);
487 ptr = memchr(str, '\r', len);
493 * If there is no more data in ringbuffer,
494 * it's just an incomplete command.
496 if (len == ringbuf_len(hfp->read_buf))
499 str2 = ringbuf_peek(hfp->read_buf, len, &len2);
503 ptr = memchr(str2, '\r', len2);
514 memcpy(ptr, str, len);
515 memcpy(ptr + len, str2, len2);
524 if (!handle_at_command(hfp, str))
526 * Command is not handled that means that was some
527 * trash. Let's skip that and keep reading from ring
533 * Command has been handled. If we are waiting for a
534 * result from upper layer, we can stop reading. If we
535 * already reply i.e. ERROR on unknown command, then we
536 * can keep reading ring buffer. Actually ring buffer
537 * should be empty but lets just look there.
539 read_again = !hfp->result_pending;
541 ringbuf_drain(hfp->read_buf, count + 1);
546 } while (read_again);
549 static void read_watch_destroy(void *user_data)
553 static bool can_read_data(struct io *io, void *user_data)
555 struct hfp_gw *hfp = user_data;
558 bytes_read = ringbuf_read(hfp->read_buf, hfp->fd);
562 if (hfp->result_pending)
570 struct hfp_gw *hfp_gw_new(int fd)
577 hfp = new0(struct hfp_gw, 1);
579 hfp->close_on_unref = false;
581 hfp->read_buf = ringbuf_new(4096);
582 if (!hfp->read_buf) {
587 hfp->write_buf = ringbuf_new(4096);
588 if (!hfp->write_buf) {
589 ringbuf_free(hfp->read_buf);
594 hfp->io = io_new(fd);
596 ringbuf_free(hfp->write_buf);
597 ringbuf_free(hfp->read_buf);
602 hfp->cmd_handlers = queue_new();
604 if (!io_set_read_handler(hfp->io, can_read_data, hfp,
605 read_watch_destroy)) {
606 queue_destroy(hfp->cmd_handlers, destroy_cmd_handler);
608 ringbuf_free(hfp->write_buf);
609 ringbuf_free(hfp->read_buf);
614 hfp->writer_active = false;
615 hfp->result_pending = false;
617 return hfp_gw_ref(hfp);
620 struct hfp_gw *hfp_gw_ref(struct hfp_gw *hfp)
625 __sync_fetch_and_add(&hfp->ref_count, 1);
630 void hfp_gw_unref(struct hfp_gw *hfp)
635 if (__sync_sub_and_fetch(&hfp->ref_count, 1))
638 hfp_gw_set_command_handler(hfp, NULL, NULL, NULL);
640 io_set_write_handler(hfp->io, NULL, NULL, NULL);
641 io_set_read_handler(hfp->io, NULL, NULL, NULL);
642 io_set_disconnect_handler(hfp->io, NULL, NULL, NULL);
647 if (hfp->close_on_unref)
650 hfp_gw_set_debug(hfp, NULL, NULL, NULL);
652 ringbuf_free(hfp->read_buf);
653 hfp->read_buf = NULL;
655 ringbuf_free(hfp->write_buf);
656 hfp->write_buf = NULL;
658 queue_destroy(hfp->cmd_handlers, destroy_cmd_handler);
659 hfp->cmd_handlers = NULL;
661 if (!hfp->in_disconnect) {
666 hfp->destroyed = true;
669 static void read_tracing(const void *buf, size_t count, void *user_data)
671 struct hfp_gw *hfp = user_data;
673 util_hexdump('>', buf, count, hfp->debug_callback, hfp->debug_data);
676 static void write_tracing(const void *buf, size_t count, void *user_data)
678 struct hfp_gw *hfp = user_data;
680 util_hexdump('<', buf, count, hfp->debug_callback, hfp->debug_data);
683 bool hfp_gw_set_debug(struct hfp_gw *hfp, hfp_debug_func_t callback,
684 void *user_data, hfp_destroy_func_t destroy)
689 if (hfp->debug_destroy)
690 hfp->debug_destroy(hfp->debug_data);
692 hfp->debug_callback = callback;
693 hfp->debug_destroy = destroy;
694 hfp->debug_data = user_data;
696 if (hfp->debug_callback) {
697 ringbuf_set_input_tracing(hfp->read_buf, read_tracing, hfp);
698 ringbuf_set_input_tracing(hfp->write_buf, write_tracing, hfp);
700 ringbuf_set_input_tracing(hfp->read_buf, NULL, NULL);
701 ringbuf_set_input_tracing(hfp->write_buf, NULL, NULL);
707 bool hfp_gw_set_close_on_unref(struct hfp_gw *hfp, bool do_close)
712 hfp->close_on_unref = do_close;
717 bool hfp_gw_send_result(struct hfp_gw *hfp, enum hfp_result result)
728 case HFP_RESULT_ERROR:
731 case HFP_RESULT_RING:
732 case HFP_RESULT_NO_CARRIER:
733 case HFP_RESULT_BUSY:
734 case HFP_RESULT_NO_ANSWER:
735 case HFP_RESULT_DELAYED:
736 case HFP_RESULT_BLACKLISTED:
737 case HFP_RESULT_CME_ERROR:
738 case HFP_RESULT_NO_DIALTONE:
739 case HFP_RESULT_CONNECT:
744 if (ringbuf_printf(hfp->write_buf, "\r\n%s\r\n", str) < 0)
750 * There might be already something to read in the ring buffer.
751 * If so, let's read it.
753 if (hfp->result_pending) {
754 hfp->result_pending = false;
761 bool hfp_gw_send_error(struct hfp_gw *hfp, enum hfp_error error)
766 if (ringbuf_printf(hfp->write_buf, "\r\n+CME ERROR: %u\r\n", error) < 0)
772 * There might be already something to read in the ring buffer.
773 * If so, let's read it.
775 if (hfp->result_pending) {
776 hfp->result_pending = false;
783 bool hfp_gw_send_info(struct hfp_gw *hfp, const char *format, ...)
792 if (asprintf(&fmt, "\r\n%s\r\n", format) < 0)
795 va_start(ap, format);
796 len = ringbuf_vprintf(hfp->write_buf, fmt, ap);
804 if (hfp->result_pending)
812 bool hfp_gw_set_command_handler(struct hfp_gw *hfp,
813 hfp_command_func_t callback,
814 void *user_data, hfp_destroy_func_t destroy)
819 if (hfp->command_destroy)
820 hfp->command_destroy(hfp->command_data);
822 hfp->command_callback = callback;
823 hfp->command_destroy = destroy;
824 hfp->command_data = user_data;
829 bool hfp_gw_register(struct hfp_gw *hfp, hfp_result_func_t callback,
832 hfp_destroy_func_t destroy)
834 struct cmd_handler *handler;
836 handler = new0(struct cmd_handler, 1);
837 handler->callback = callback;
838 handler->user_data = user_data;
840 handler->prefix = strdup(prefix);
841 if (!handler->prefix) {
846 if (queue_find(hfp->cmd_handlers, match_handler_prefix,
848 destroy_cmd_handler(handler);
852 handler->destroy = destroy;
854 return queue_push_tail(hfp->cmd_handlers, handler);
857 bool hfp_gw_unregister(struct hfp_gw *hfp, const char *prefix)
859 struct cmd_handler *handler;
862 lookup_prefix = strdup(prefix);
866 handler = queue_remove_if(hfp->cmd_handlers, match_handler_prefix,
873 destroy_cmd_handler(handler);
878 static void disconnect_watch_destroy(void *user_data)
880 struct hfp_gw *hfp = user_data;
882 if (hfp->disconnect_destroy)
883 hfp->disconnect_destroy(hfp->disconnect_data);
889 static bool io_disconnected(struct io *io, void *user_data)
891 struct hfp_gw *hfp = user_data;
893 hfp->in_disconnect = true;
895 if (hfp->disconnect_callback)
896 hfp->disconnect_callback(hfp->disconnect_data);
898 hfp->in_disconnect = false;
903 bool hfp_gw_set_disconnect_handler(struct hfp_gw *hfp,
904 hfp_disconnect_func_t callback,
906 hfp_destroy_func_t destroy)
911 if (hfp->disconnect_destroy)
912 hfp->disconnect_destroy(hfp->disconnect_data);
914 if (!io_set_disconnect_handler(hfp->io, io_disconnected, hfp,
915 disconnect_watch_destroy)) {
916 hfp->disconnect_callback = NULL;
917 hfp->disconnect_destroy = NULL;
918 hfp->disconnect_data = NULL;
922 hfp->disconnect_callback = callback;
923 hfp->disconnect_destroy = destroy;
924 hfp->disconnect_data = user_data;
929 bool hfp_gw_disconnect(struct hfp_gw *hfp)
934 return io_shutdown(hfp->io);
937 static bool match_handler_event_prefix(const void *a, const void *b)
939 const struct event_handler *handler = a;
940 const char *prefix = b;
942 if (strcmp(handler->prefix, prefix) != 0)
948 static void destroy_event_handler(void *data)
950 struct event_handler *handler = data;
952 if (handler->destroy)
953 handler->destroy(handler->user_data);
955 free(handler->prefix);
960 static bool hf_can_write_data(struct io *io, void *user_data)
962 struct hfp_hf *hfp = user_data;
963 ssize_t bytes_written;
965 bytes_written = ringbuf_write(hfp->write_buf, hfp->fd);
966 if (bytes_written < 0)
969 if (ringbuf_len(hfp->write_buf) > 0)
975 static void hf_write_watch_destroy(void *user_data)
977 struct hfp_hf *hfp = user_data;
979 hfp->writer_active = false;
982 static void hf_skip_whitespace(struct hfp_context *context)
984 while (context->data[context->offset] == ' ')
988 static bool is_response(const char *prefix, enum hfp_result *result,
989 enum hfp_error *cme_err,
990 struct hfp_context *context)
992 if (strcmp(prefix, "OK") == 0) {
993 *result = HFP_RESULT_OK;
995 * Set cme_err to 0 as this is not valid when result is not
1002 if (strcmp(prefix, "ERROR") == 0) {
1003 *result = HFP_RESULT_ERROR;
1008 if (strcmp(prefix, "NO CARRIER") == 0) {
1009 *result = HFP_RESULT_NO_CARRIER;
1014 if (strcmp(prefix, "NO ANSWER") == 0) {
1015 *result = HFP_RESULT_NO_ANSWER;
1020 if (strcmp(prefix, "BUSY") == 0) {
1021 *result = HFP_RESULT_BUSY;
1026 if (strcmp(prefix, "DELAYED") == 0) {
1027 *result = HFP_RESULT_DELAYED;
1032 if (strcmp(prefix, "BLACKLISTED") == 0) {
1033 *result = HFP_RESULT_BLACKLISTED;
1038 if (strcmp(prefix, "+CME ERROR") == 0) {
1041 *result = HFP_RESULT_CME_ERROR;
1043 if (hfp_context_get_number(context, &val) &&
1044 val <= HFP_ERROR_NETWORK_NOT_ALLOWED)
1047 *cme_err = HFP_ERROR_AG_FAILURE;
1055 static void hf_wakeup_writer(struct hfp_hf *hfp)
1057 if (hfp->writer_active)
1060 if (!ringbuf_len(hfp->write_buf))
1063 if (!io_set_write_handler(hfp->io, hf_can_write_data,
1064 hfp, hf_write_watch_destroy))
1067 hfp->writer_active = true;
1070 static void hf_call_prefix_handler(struct hfp_hf *hfp, const char *data)
1072 struct event_handler *handler;
1073 const char *separators = ";:\0";
1074 struct hfp_context context;
1075 enum hfp_result result;
1076 enum hfp_error cme_err;
1077 char lookup_prefix[18];
1078 uint8_t pref_len = 0;
1083 context.data = data;
1085 hf_skip_whitespace(&context);
1087 if (strlen(data + context.offset) < 2)
1090 prefix = data + context.offset;
1092 pref_len = strcspn(prefix, separators);
1093 if (pref_len > 17 || pref_len < 2)
1096 for (i = 0; i < pref_len; i++)
1097 lookup_prefix[i] = toupper(prefix[i]);
1099 lookup_prefix[pref_len] = '\0';
1100 context.offset += pref_len + 1;
1102 if (is_response(lookup_prefix, &result, &cme_err, &context)) {
1103 struct cmd_response *cmd;
1105 cmd = queue_peek_head(hfp->cmd_queue);
1109 cmd->resp_cb(result, cme_err, cmd->user_data);
1111 queue_remove(hfp->cmd_queue, cmd);
1114 hf_wakeup_writer(hfp);
1118 handler = queue_find(hfp->event_handlers, match_handler_event_prefix,
1123 handler->callback(&context, handler->user_data);
1126 static char *find_cr_lf(char *str, size_t len)
1129 size_t count, offset;
1133 ptr = memchr(str, '\r', len);
1136 * Check if there is more data after '\r'. If so check for
1140 if ((count < (len - 1)) && *(ptr + 1) == '\n')
1143 /* There is only '\r'? Let's try to find next one */
1144 offset += count + 1;
1149 ptr = memchr(str + offset, '\r', len - offset);
1155 static void hf_process_input(struct hfp_hf *hfp)
1157 char *str, *ptr, *str2, *tmp;
1158 size_t len, count, offset, len2;
1159 bool free_tmp = false;
1161 str = ringbuf_peek(hfp->read_buf, 0, &len);
1167 ptr = find_cr_lf(str, len);
1169 count = ptr - (str + offset);
1171 /* 2 is for <cr><lf> */
1175 hf_call_prefix_handler(hfp, str + offset);
1176 offset += count + 2;
1179 ptr = find_cr_lf(str + offset, len - offset);
1183 * Just check if there is no wrapped data in ring buffer.
1184 * Should not happen too often
1186 if (len == ringbuf_len(hfp->read_buf))
1189 str2 = ringbuf_peek(hfp->read_buf, len, &len2);
1193 ptr = find_cr_lf(str2, len2);
1195 /* Might happen that we wrap between \r and \n */
1196 ptr = memchr(str2, '\n', len2);
1206 tmp = malloc(len + count);
1210 /* "str" here is not a string so we need to use memcpy */
1211 memcpy(tmp, str, len);
1212 memcpy(tmp + len, str2, count);
1220 hf_call_prefix_handler(hfp, tmp);
1224 ringbuf_drain(hfp->read_buf, offset);
1230 static bool hf_can_read_data(struct io *io, void *user_data)
1232 struct hfp_hf *hfp = user_data;
1235 bytes_read = ringbuf_read(hfp->read_buf, hfp->fd);
1239 hf_process_input(hfp);
1244 struct hfp_hf *hfp_hf_new(int fd)
1251 hfp = new0(struct hfp_hf, 1);
1253 hfp->close_on_unref = false;
1255 hfp->read_buf = ringbuf_new(4096);
1256 if (!hfp->read_buf) {
1261 hfp->write_buf = ringbuf_new(4096);
1262 if (!hfp->write_buf) {
1263 ringbuf_free(hfp->read_buf);
1268 hfp->io = io_new(fd);
1270 ringbuf_free(hfp->write_buf);
1271 ringbuf_free(hfp->read_buf);
1276 hfp->event_handlers = queue_new();
1277 hfp->cmd_queue = queue_new();
1278 hfp->writer_active = false;
1280 if (!io_set_read_handler(hfp->io, hf_can_read_data, hfp,
1281 read_watch_destroy)) {
1282 queue_destroy(hfp->event_handlers,
1283 destroy_event_handler);
1284 io_destroy(hfp->io);
1285 ringbuf_free(hfp->write_buf);
1286 ringbuf_free(hfp->read_buf);
1291 return hfp_hf_ref(hfp);
1294 struct hfp_hf *hfp_hf_ref(struct hfp_hf *hfp)
1299 __sync_fetch_and_add(&hfp->ref_count, 1);
1304 void hfp_hf_unref(struct hfp_hf *hfp)
1309 if (__sync_sub_and_fetch(&hfp->ref_count, 1))
1312 io_set_write_handler(hfp->io, NULL, NULL, NULL);
1313 io_set_read_handler(hfp->io, NULL, NULL, NULL);
1314 io_set_disconnect_handler(hfp->io, NULL, NULL, NULL);
1316 io_destroy(hfp->io);
1319 if (hfp->close_on_unref)
1322 hfp_hf_set_debug(hfp, NULL, NULL, NULL);
1324 ringbuf_free(hfp->read_buf);
1325 hfp->read_buf = NULL;
1327 ringbuf_free(hfp->write_buf);
1328 hfp->write_buf = NULL;
1330 queue_destroy(hfp->event_handlers, destroy_event_handler);
1331 hfp->event_handlers = NULL;
1333 queue_destroy(hfp->cmd_queue, free);
1334 hfp->cmd_queue = NULL;
1336 if (!hfp->in_disconnect) {
1341 hfp->destroyed = true;
1344 static void hf_read_tracing(const void *buf, size_t count,
1347 struct hfp_hf *hfp = user_data;
1349 util_hexdump('>', buf, count, hfp->debug_callback, hfp->debug_data);
1352 static void hf_write_tracing(const void *buf, size_t count,
1355 struct hfp_hf *hfp = user_data;
1357 util_hexdump('<', buf, count, hfp->debug_callback, hfp->debug_data);
1360 bool hfp_hf_set_debug(struct hfp_hf *hfp, hfp_debug_func_t callback,
1361 void *user_data, hfp_destroy_func_t destroy)
1366 if (hfp->debug_destroy)
1367 hfp->debug_destroy(hfp->debug_data);
1369 hfp->debug_callback = callback;
1370 hfp->debug_destroy = destroy;
1371 hfp->debug_data = user_data;
1373 if (hfp->debug_callback) {
1374 ringbuf_set_input_tracing(hfp->read_buf, hf_read_tracing, hfp);
1375 ringbuf_set_input_tracing(hfp->write_buf, hf_write_tracing,
1378 ringbuf_set_input_tracing(hfp->read_buf, NULL, NULL);
1379 ringbuf_set_input_tracing(hfp->write_buf, NULL, NULL);
1385 bool hfp_hf_set_close_on_unref(struct hfp_hf *hfp, bool do_close)
1390 hfp->close_on_unref = do_close;
1395 bool hfp_hf_send_command(struct hfp_hf *hfp, hfp_response_func_t resp_cb,
1396 void *user_data, const char *format, ...)
1401 struct cmd_response *cmd;
1403 if (!hfp || !format || !resp_cb)
1406 if (asprintf(&fmt, "%s\r", format) < 0)
1409 cmd = new0(struct cmd_response, 1);
1411 va_start(ap, format);
1412 len = ringbuf_vprintf(hfp->write_buf, fmt, ap);
1422 cmd->resp_cb = resp_cb;
1423 cmd->user_data = user_data;
1425 if (!queue_push_tail(hfp->cmd_queue, cmd)) {
1426 ringbuf_drain(hfp->write_buf, len);
1431 hf_wakeup_writer(hfp);
1436 bool hfp_hf_register(struct hfp_hf *hfp, hfp_hf_result_func_t callback,
1439 hfp_destroy_func_t destroy)
1441 struct event_handler *handler;
1446 handler = new0(struct event_handler, 1);
1447 handler->callback = callback;
1448 handler->user_data = user_data;
1450 handler->prefix = strdup(prefix);
1451 if (!handler->prefix) {
1456 if (queue_find(hfp->event_handlers, match_handler_event_prefix,
1458 destroy_event_handler(handler);
1462 handler->destroy = destroy;
1464 return queue_push_tail(hfp->event_handlers, handler);
1467 bool hfp_hf_unregister(struct hfp_hf *hfp, const char *prefix)
1469 struct cmd_handler *handler;
1471 /* Cast to void as queue_remove needs that */
1472 handler = queue_remove_if(hfp->event_handlers,
1473 match_handler_event_prefix,
1479 destroy_event_handler(handler);
1484 static void hf_disconnect_watch_destroy(void *user_data)
1486 struct hfp_hf *hfp = user_data;
1488 if (hfp->disconnect_destroy)
1489 hfp->disconnect_destroy(hfp->disconnect_data);
1495 static bool hf_io_disconnected(struct io *io, void *user_data)
1497 struct hfp_hf *hfp = user_data;
1499 hfp->in_disconnect = true;
1501 if (hfp->disconnect_callback)
1502 hfp->disconnect_callback(hfp->disconnect_data);
1504 hfp->in_disconnect = false;
1509 bool hfp_hf_set_disconnect_handler(struct hfp_hf *hfp,
1510 hfp_disconnect_func_t callback,
1512 hfp_destroy_func_t destroy)
1517 if (hfp->disconnect_destroy)
1518 hfp->disconnect_destroy(hfp->disconnect_data);
1520 if (!io_set_disconnect_handler(hfp->io, hf_io_disconnected, hfp,
1521 hf_disconnect_watch_destroy)) {
1522 hfp->disconnect_callback = NULL;
1523 hfp->disconnect_destroy = NULL;
1524 hfp->disconnect_data = NULL;
1528 hfp->disconnect_callback = callback;
1529 hfp->disconnect_destroy = destroy;
1530 hfp->disconnect_data = user_data;
1535 bool hfp_hf_disconnect(struct hfp_hf *hfp)
1540 return io_shutdown(hfp->io);