summaryrefslogtreecommitdiffstats
path: root/hci/src/hci_hal.c
blob: f2b48153f3add96d5e067979455cd47f637006c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/******************************************************************************
 *
 *  Copyright (C) 2014 Google, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/
#include <string.h>
#include "hci_hal.h"
#include "hci_internals.h"
#include "bt_utils.h"
#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
#include <assert.h>
#include "osi/include/eager_reader.h"
#include "osi/include/osi.h"
#include "osi/include/log.h"
#endif

bt_soc_type soc_type;

const hci_hal_t *hci_hal_get_interface() {
    soc_type = get_soc_type();

    if (soc_type == BT_SOC_ROME || soc_type == BT_SOC_CHEROKEE
            || soc_type == BT_SOC_DEFAULT) {
        return hci_hal_h4_get_interface();
    } else {
        return hci_hal_mct_get_interface();
    }
}

#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))
void hci_reader_free(hci_reader_t *reader) {
  if (!reader)
    return;

  // Only unregister from the input if we actually did register
  if (reader->inbound_read_object)
    reactor_unregister(reader->inbound_read_object);

  // Free the current buffer, because it's not in the queue
  // and won't be freed below
  if (reader->data_buffer)
    osi_free(reader->data_buffer);

  osi_free(reader);
}

hci_reader_t *hci_reader_new(
    int fd_to_read,
    size_t buffer_size,
    size_t max_buffer_count,
    thread_t *thread,
    hci_reader_cb read_cb
    ) {

  assert(fd_to_read != INVALID_FD);
  assert(buffer_size > 0);
  assert(max_buffer_count > 0);


  hci_reader_t *ret = osi_calloc(sizeof(hci_reader_t));
  if (!ret) {
    LOG_ERROR("%s unable to allocate memory for new hci_reader.", __func__);
    goto error;
  }

  ret->inbound_fd = fd_to_read;

  ret->data_buffer = osi_calloc(buffer_size);
  ret->buffer_size = buffer_size;
  ret->rd_ptr = 0;
  ret->wr_ptr = 0;

  ret->inbound_read_thread = thread;
  if (!ret->inbound_read_thread) {
    LOG_ERROR("%s unable to make reading thread.", __func__);
    goto error;
  }

  ret->inbound_read_object = reactor_register(
      thread_get_reactor(ret->inbound_read_thread),
      fd_to_read,
      ret,
      read_cb,
      NULL
      );

  return ret;

error:;
  hci_reader_free(ret);
  return NULL;
}

size_t hci_reader_read(hci_reader_t *reader, uint8_t *buffer, size_t req_size) {
  int bytes_read = 0;
  assert(reader != NULL);
  assert(buffer != NULL);

  // If the caller wants nonblocking behavior, poll to see if we have
  // any bytes available before reading.
  if (reader->rd_ptr < reader->wr_ptr) {
    bytes_read = reader->wr_ptr - reader->rd_ptr;
    if ((size_t) bytes_read > req_size)
      bytes_read = req_size;
    memcpy(buffer, reader->data_buffer+reader->rd_ptr, bytes_read);
    reader->rd_ptr += bytes_read;
  } else {
    bytes_read = read(reader->inbound_fd, buffer, req_size);
    if(bytes_read == -1)
      bytes_read = 0;
  }

  return bytes_read;
}
#endif