Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of BTstack by
USBHostBTstack/USBHostBTstack.cpp@2:871b41f4789e, 2013-03-22 (annotated)
- Committer:
- va009039
- Date:
- Fri Mar 22 22:35:57 2013 +0000
- Revision:
- 2:871b41f4789e
- Parent:
- 1:b657594559be
change to single thread
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| va009039 | 2:871b41f4789e | 1 | // USBHostBTstack.cpp |
| va009039 | 1:b657594559be | 2 | #include "USBHostBTstack.h" |
| va009039 | 1:b657594559be | 3 | #include "dbg.h" |
| va009039 | 1:b657594559be | 4 | |
| va009039 | 2:871b41f4789e | 5 | //#define BTSTACK_DEBUG |
| va009039 | 1:b657594559be | 6 | |
| va009039 | 1:b657594559be | 7 | #ifdef BTSTACK_DEBUG |
| va009039 | 1:b657594559be | 8 | #define BT_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); |
| va009039 | 2:871b41f4789e | 9 | #define BT_DBG_BYTES(STR,BUF,LEN) _debug_bytes(__PRETTY_FUNCTION__,__LINE__,STR,BUF,LEN) |
| va009039 | 1:b657594559be | 10 | #else |
| va009039 | 1:b657594559be | 11 | #define BT_DBG(...) while(0); |
| va009039 | 2:871b41f4789e | 12 | #define BT_DBG_BYTES(S,BUF,LEN) while(0); |
| va009039 | 1:b657594559be | 13 | #endif |
| va009039 | 1:b657594559be | 14 | |
| va009039 | 1:b657594559be | 15 | #define HCI_COMMAND_DATA_PACKET 0x01 |
| va009039 | 1:b657594559be | 16 | #define HCI_ACL_DATA_PACKET 0x02 |
| va009039 | 1:b657594559be | 17 | #define HCI_SCO_DATA_PACKET 0x03 |
| va009039 | 1:b657594559be | 18 | #define HCI_EVENT_PACKET 0x04 |
| va009039 | 1:b657594559be | 19 | |
| va009039 | 1:b657594559be | 20 | USBHostBTstack::USBHostBTstack() |
| va009039 | 1:b657594559be | 21 | { |
| va009039 | 1:b657594559be | 22 | host = USBHost::getHostInst(); |
| va009039 | 1:b657594559be | 23 | init(); |
| va009039 | 1:b657594559be | 24 | m_pCb = NULL; |
| va009039 | 1:b657594559be | 25 | } |
| va009039 | 1:b657594559be | 26 | |
| va009039 | 1:b657594559be | 27 | void USBHostBTstack::init() |
| va009039 | 1:b657594559be | 28 | { |
| va009039 | 1:b657594559be | 29 | BT_DBG(""); |
| va009039 | 1:b657594559be | 30 | dev = NULL; |
| va009039 | 1:b657594559be | 31 | int_in = NULL; |
| va009039 | 1:b657594559be | 32 | bulk_in = NULL; |
| va009039 | 1:b657594559be | 33 | bulk_out = NULL; |
| va009039 | 1:b657594559be | 34 | btstack_intf = -1; |
| va009039 | 1:b657594559be | 35 | btstack_device_found = false; |
| va009039 | 1:b657594559be | 36 | dev_connected = false; |
| va009039 | 1:b657594559be | 37 | ep_int_in = false; |
| va009039 | 1:b657594559be | 38 | ep_bulk_in = false; |
| va009039 | 1:b657594559be | 39 | ep_bulk_out = false; |
| va009039 | 1:b657594559be | 40 | } |
| va009039 | 1:b657594559be | 41 | |
| va009039 | 1:b657594559be | 42 | bool USBHostBTstack::connected() |
| va009039 | 1:b657594559be | 43 | { |
| va009039 | 1:b657594559be | 44 | return dev_connected; |
| va009039 | 1:b657594559be | 45 | } |
| va009039 | 1:b657594559be | 46 | |
| va009039 | 1:b657594559be | 47 | bool USBHostBTstack::connect() |
| va009039 | 1:b657594559be | 48 | { |
| va009039 | 1:b657594559be | 49 | if (dev_connected) { |
| va009039 | 1:b657594559be | 50 | return true; |
| va009039 | 1:b657594559be | 51 | } |
| va009039 | 1:b657594559be | 52 | |
| va009039 | 1:b657594559be | 53 | for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { |
| va009039 | 1:b657594559be | 54 | if ((dev = host->getDevice(i)) != NULL) { |
| va009039 | 1:b657594559be | 55 | |
| va009039 | 1:b657594559be | 56 | BT_DBG("Trying to connect BTstack device\r\n"); |
| va009039 | 1:b657594559be | 57 | |
| va009039 | 1:b657594559be | 58 | if(host->enumerate(dev, this)) { |
| va009039 | 1:b657594559be | 59 | break; |
| va009039 | 1:b657594559be | 60 | } |
| va009039 | 1:b657594559be | 61 | if (btstack_device_found) { |
| va009039 | 1:b657594559be | 62 | int_in = dev->getEndpoint(btstack_intf, INTERRUPT_ENDPOINT, IN); |
| va009039 | 1:b657594559be | 63 | bulk_in = dev->getEndpoint(btstack_intf, BULK_ENDPOINT, IN); |
| va009039 | 1:b657594559be | 64 | bulk_out = dev->getEndpoint(btstack_intf, BULK_ENDPOINT, OUT); |
| va009039 | 1:b657594559be | 65 | if (!int_in || !bulk_in || !bulk_out) { |
| va009039 | 1:b657594559be | 66 | continue; |
| va009039 | 1:b657594559be | 67 | } |
| va009039 | 1:b657594559be | 68 | USB_INFO("New BTstack device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, btstack_intf); |
| va009039 | 1:b657594559be | 69 | dev->setName("BTstack", btstack_intf); |
| va009039 | 1:b657594559be | 70 | host->registerDriver(dev, btstack_intf, this, &USBHostBTstack::init); |
| va009039 | 1:b657594559be | 71 | |
| va009039 | 1:b657594559be | 72 | int_in->attach(this, &USBHostBTstack::int_rxHandler); |
| va009039 | 1:b657594559be | 73 | host->interruptRead(dev, int_in, int_report, int_in->getSize(), false); |
| va009039 | 1:b657594559be | 74 | |
| va009039 | 1:b657594559be | 75 | bulk_in->attach(this, &USBHostBTstack::bulk_rxHandler); |
| va009039 | 1:b657594559be | 76 | host->bulkRead(dev, bulk_in, bulk_report, bulk_in->getSize(), false); |
| va009039 | 1:b657594559be | 77 | |
| va009039 | 1:b657594559be | 78 | dev_connected = true; |
| va009039 | 1:b657594559be | 79 | return true; |
| va009039 | 1:b657594559be | 80 | } |
| va009039 | 1:b657594559be | 81 | } |
| va009039 | 1:b657594559be | 82 | } |
| va009039 | 1:b657594559be | 83 | init(); |
| va009039 | 1:b657594559be | 84 | return false; |
| va009039 | 1:b657594559be | 85 | } |
| va009039 | 1:b657594559be | 86 | |
| va009039 | 2:871b41f4789e | 87 | void USBHostBTstack::int_rxHandler() |
| va009039 | 2:871b41f4789e | 88 | { |
| va009039 | 1:b657594559be | 89 | int len = int_in->getLengthTransferred(); |
| va009039 | 2:871b41f4789e | 90 | BT_DBG_BYTES("HCI_EVT:", int_report, len); |
| va009039 | 2:871b41f4789e | 91 | Packet* pkt = mail_box.alloc(); |
| va009039 | 2:871b41f4789e | 92 | TEST_ASSERT(pkt); |
| va009039 | 2:871b41f4789e | 93 | pkt->type = HCI_EVENT_PACKET; |
| va009039 | 2:871b41f4789e | 94 | pkt->buf = int_report; |
| va009039 | 2:871b41f4789e | 95 | pkt->len = len; |
| va009039 | 2:871b41f4789e | 96 | mail_box.put(pkt); |
| va009039 | 1:b657594559be | 97 | } |
| va009039 | 1:b657594559be | 98 | |
| va009039 | 2:871b41f4789e | 99 | void USBHostBTstack::bulk_rxHandler() |
| va009039 | 2:871b41f4789e | 100 | { |
| va009039 | 1:b657594559be | 101 | int len = bulk_in->getLengthTransferred(); |
| va009039 | 2:871b41f4789e | 102 | BT_DBG_BYTES("ACL_RCV:", bulk_report, len); |
| va009039 | 2:871b41f4789e | 103 | Packet* pkt = mail_box.alloc(); |
| va009039 | 2:871b41f4789e | 104 | TEST_ASSERT(pkt); |
| va009039 | 2:871b41f4789e | 105 | pkt->type = HCI_ACL_DATA_PACKET; |
| va009039 | 2:871b41f4789e | 106 | pkt->buf = bulk_report; |
| va009039 | 2:871b41f4789e | 107 | pkt->len = len; |
| va009039 | 2:871b41f4789e | 108 | mail_box.put(pkt); |
| va009039 | 1:b657594559be | 109 | } |
| va009039 | 1:b657594559be | 110 | |
| va009039 | 1:b657594559be | 111 | /*virtual*/ void USBHostBTstack::setVidPid(uint16_t vid, uint16_t pid) |
| va009039 | 1:b657594559be | 112 | { |
| va009039 | 1:b657594559be | 113 | BT_DBG("vid:%04x,pid:%04x", vid, pid); |
| va009039 | 1:b657594559be | 114 | } |
| va009039 | 1:b657594559be | 115 | |
| va009039 | 1:b657594559be | 116 | /*virtual*/ bool USBHostBTstack::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed |
| va009039 | 1:b657594559be | 117 | { |
| va009039 | 1:b657594559be | 118 | BT_DBG("intf_nb=%d,intf_class=%02X,intf_subclass=%d,intf_protocol=%d", intf_nb, intf_class, intf_subclass, intf_protocol); |
| va009039 | 1:b657594559be | 119 | if ((btstack_intf == -1) && intf_class == 0xe0) { |
| va009039 | 1:b657594559be | 120 | btstack_intf = intf_nb; |
| va009039 | 1:b657594559be | 121 | return true; |
| va009039 | 1:b657594559be | 122 | } |
| va009039 | 1:b657594559be | 123 | return false; |
| va009039 | 1:b657594559be | 124 | } |
| va009039 | 1:b657594559be | 125 | |
| va009039 | 1:b657594559be | 126 | /*virtual*/ bool USBHostBTstack::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used |
| va009039 | 1:b657594559be | 127 | { |
| va009039 | 1:b657594559be | 128 | BT_DBG("intf_nb:%d,type:%d,dir:%d",intf_nb, type, dir); |
| va009039 | 1:b657594559be | 129 | if (intf_nb == btstack_intf) { |
| va009039 | 1:b657594559be | 130 | if (ep_int_in == false && type == INTERRUPT_ENDPOINT && dir == IN) { |
| va009039 | 1:b657594559be | 131 | ep_int_in = true; |
| va009039 | 1:b657594559be | 132 | } else if (ep_bulk_in == false && type == BULK_ENDPOINT && dir == IN) { |
| va009039 | 1:b657594559be | 133 | ep_bulk_in = true; |
| va009039 | 1:b657594559be | 134 | } else if (ep_bulk_out == false && type == BULK_ENDPOINT && dir == OUT) { |
| va009039 | 1:b657594559be | 135 | ep_bulk_out = true; |
| va009039 | 1:b657594559be | 136 | } else { |
| va009039 | 1:b657594559be | 137 | return false; |
| va009039 | 1:b657594559be | 138 | } |
| va009039 | 1:b657594559be | 139 | if (ep_int_in && ep_bulk_in && ep_bulk_out) { |
| va009039 | 1:b657594559be | 140 | btstack_device_found = true; |
| va009039 | 1:b657594559be | 141 | } |
| va009039 | 1:b657594559be | 142 | return true; |
| va009039 | 1:b657594559be | 143 | } |
| va009039 | 1:b657594559be | 144 | return false; |
| va009039 | 1:b657594559be | 145 | } |
| va009039 | 1:b657594559be | 146 | |
| va009039 | 1:b657594559be | 147 | int USBHostBTstack::open() |
| va009039 | 1:b657594559be | 148 | { |
| va009039 | 1:b657594559be | 149 | BT_DBG("%p", this); |
| va009039 | 1:b657594559be | 150 | while(!connected()) { |
| va009039 | 1:b657594559be | 151 | if (connect()) { |
| va009039 | 1:b657594559be | 152 | break; |
| va009039 | 1:b657594559be | 153 | } |
| va009039 | 1:b657594559be | 154 | Thread::wait(500); |
| va009039 | 1:b657594559be | 155 | } |
| va009039 | 1:b657594559be | 156 | return 0; |
| va009039 | 1:b657594559be | 157 | } |
| va009039 | 1:b657594559be | 158 | |
| va009039 | 1:b657594559be | 159 | int USBHostBTstack::send_packet(uint8_t packet_type, uint8_t* packet, int size) |
| va009039 | 1:b657594559be | 160 | { |
| va009039 | 1:b657594559be | 161 | USB_TYPE res; |
| va009039 | 1:b657594559be | 162 | switch(packet_type){ |
| va009039 | 1:b657594559be | 163 | case HCI_COMMAND_DATA_PACKET: |
| va009039 | 2:871b41f4789e | 164 | BT_DBG_BYTES("HCI_CMD:", packet, size); |
| va009039 | 1:b657594559be | 165 | res = host->controlWrite(dev, |
| va009039 | 1:b657594559be | 166 | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_DEVICE, |
| va009039 | 1:b657594559be | 167 | 0, 0, 0, packet, size); |
| va009039 | 1:b657594559be | 168 | TEST_ASSERT(res == USB_TYPE_OK); |
| va009039 | 1:b657594559be | 169 | break; |
| va009039 | 1:b657594559be | 170 | case HCI_ACL_DATA_PACKET: |
| va009039 | 2:871b41f4789e | 171 | BT_DBG_BYTES("ACL_SND:", packet, size); |
| va009039 | 1:b657594559be | 172 | res = host->bulkWrite(dev, bulk_out, packet, size); |
| va009039 | 1:b657594559be | 173 | TEST_ASSERT(res == USB_TYPE_OK); |
| va009039 | 1:b657594559be | 174 | break; |
| va009039 | 1:b657594559be | 175 | default: |
| va009039 | 1:b657594559be | 176 | TEST_ASSERT(0); |
| va009039 | 1:b657594559be | 177 | } |
| va009039 | 1:b657594559be | 178 | return 0; |
| va009039 | 1:b657594559be | 179 | } |
| va009039 | 1:b657594559be | 180 | |
| va009039 | 1:b657594559be | 181 | void USBHostBTstack::register_packet_handler(void (*pMethod)(uint8_t, uint8_t*, uint16_t) ) |
| va009039 | 1:b657594559be | 182 | { |
| va009039 | 1:b657594559be | 183 | BT_DBG("pMethod: %p", pMethod); |
| va009039 | 1:b657594559be | 184 | m_pCb = pMethod; |
| va009039 | 1:b657594559be | 185 | } |
| va009039 | 1:b657594559be | 186 | |
| va009039 | 2:871b41f4789e | 187 | void USBHostBTstack::poll() |
| va009039 | 2:871b41f4789e | 188 | { |
| va009039 | 2:871b41f4789e | 189 | osEvent evt = mail_box.get(0); // non-blocking |
| va009039 | 2:871b41f4789e | 190 | if (evt.status == osEventMail) { |
| va009039 | 2:871b41f4789e | 191 | Packet* pkt = reinterpret_cast<Packet*>(evt.value.p); |
| va009039 | 2:871b41f4789e | 192 | TEST_ASSERT(pkt); |
| va009039 | 2:871b41f4789e | 193 | //BT_DBG("type: %d, buf: %p, len: %d", pkt->type, pkt->buf, pkt->len); |
| va009039 | 2:871b41f4789e | 194 | if (m_pCb) { |
| va009039 | 2:871b41f4789e | 195 | m_pCb(pkt->type, pkt->buf, pkt->len); |
| va009039 | 2:871b41f4789e | 196 | } |
| va009039 | 2:871b41f4789e | 197 | if (dev) { |
| va009039 | 2:871b41f4789e | 198 | if (pkt->type == HCI_EVENT_PACKET) { |
| va009039 | 2:871b41f4789e | 199 | host->interruptRead(dev, int_in, int_report, int_in->getSize(), false); |
| va009039 | 2:871b41f4789e | 200 | } else { // HCI_ACL_DATA_PACKET |
| va009039 | 2:871b41f4789e | 201 | host->bulkRead(dev, bulk_in, bulk_report, bulk_in->getSize(), false); |
| va009039 | 2:871b41f4789e | 202 | } |
| va009039 | 2:871b41f4789e | 203 | } |
| va009039 | 2:871b41f4789e | 204 | mail_box.free(pkt); |
| va009039 | 2:871b41f4789e | 205 | } |
| va009039 | 2:871b41f4789e | 206 | } |
| va009039 | 2:871b41f4789e | 207 | |
| va009039 | 2:871b41f4789e | 208 | void _debug_bytes(const char* pretty, int line, const char* s, uint8_t* buf, int len) |
| va009039 | 2:871b41f4789e | 209 | { |
| va009039 | 2:871b41f4789e | 210 | printf("[%s:%d]\n%s", pretty, line, s); |
| va009039 | 2:871b41f4789e | 211 | for(int i = 0; i < len; i++) { |
| va009039 | 2:871b41f4789e | 212 | printf(" %02x", buf[i]); |
| va009039 | 2:871b41f4789e | 213 | } |
| va009039 | 2:871b41f4789e | 214 | printf("\n"); |
| va009039 | 2:871b41f4789e | 215 | } |
