mbed base bard check program for BlueTooth USB dongle module (3 switches, 6 leds, I2C LCD, A/D)
Fork of BTstack by
USBHostBTstack/USBHostBTstack.cpp
- Committer:
- va009039
- Date:
- 2013-03-22
- Revision:
- 2:871b41f4789e
- Parent:
- 1:b657594559be
File content as of revision 2:871b41f4789e:
// USBHostBTstack.cpp #include "USBHostBTstack.h" #include "dbg.h" //#define BTSTACK_DEBUG #ifdef BTSTACK_DEBUG #define BT_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); #define BT_DBG_BYTES(STR,BUF,LEN) _debug_bytes(__PRETTY_FUNCTION__,__LINE__,STR,BUF,LEN) #else #define BT_DBG(...) while(0); #define BT_DBG_BYTES(S,BUF,LEN) while(0); #endif #define HCI_COMMAND_DATA_PACKET 0x01 #define HCI_ACL_DATA_PACKET 0x02 #define HCI_SCO_DATA_PACKET 0x03 #define HCI_EVENT_PACKET 0x04 USBHostBTstack::USBHostBTstack() { host = USBHost::getHostInst(); init(); m_pCb = NULL; } void USBHostBTstack::init() { BT_DBG(""); dev = NULL; int_in = NULL; bulk_in = NULL; bulk_out = NULL; btstack_intf = -1; btstack_device_found = false; dev_connected = false; ep_int_in = false; ep_bulk_in = false; ep_bulk_out = false; } bool USBHostBTstack::connected() { return dev_connected; } bool USBHostBTstack::connect() { if (dev_connected) { return true; } for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { if ((dev = host->getDevice(i)) != NULL) { BT_DBG("Trying to connect BTstack device\r\n"); if(host->enumerate(dev, this)) { break; } if (btstack_device_found) { int_in = dev->getEndpoint(btstack_intf, INTERRUPT_ENDPOINT, IN); bulk_in = dev->getEndpoint(btstack_intf, BULK_ENDPOINT, IN); bulk_out = dev->getEndpoint(btstack_intf, BULK_ENDPOINT, OUT); if (!int_in || !bulk_in || !bulk_out) { continue; } USB_INFO("New BTstack device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, btstack_intf); dev->setName("BTstack", btstack_intf); host->registerDriver(dev, btstack_intf, this, &USBHostBTstack::init); int_in->attach(this, &USBHostBTstack::int_rxHandler); host->interruptRead(dev, int_in, int_report, int_in->getSize(), false); bulk_in->attach(this, &USBHostBTstack::bulk_rxHandler); host->bulkRead(dev, bulk_in, bulk_report, bulk_in->getSize(), false); dev_connected = true; return true; } } } init(); return false; } void USBHostBTstack::int_rxHandler() { int len = int_in->getLengthTransferred(); BT_DBG_BYTES("HCI_EVT:", int_report, len); Packet* pkt = mail_box.alloc(); TEST_ASSERT(pkt); pkt->type = HCI_EVENT_PACKET; pkt->buf = int_report; pkt->len = len; mail_box.put(pkt); } void USBHostBTstack::bulk_rxHandler() { int len = bulk_in->getLengthTransferred(); BT_DBG_BYTES("ACL_RCV:", bulk_report, len); Packet* pkt = mail_box.alloc(); TEST_ASSERT(pkt); pkt->type = HCI_ACL_DATA_PACKET; pkt->buf = bulk_report; pkt->len = len; mail_box.put(pkt); } /*virtual*/ void USBHostBTstack::setVidPid(uint16_t vid, uint16_t pid) { BT_DBG("vid:%04x,pid:%04x", vid, pid); } /*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 { BT_DBG("intf_nb=%d,intf_class=%02X,intf_subclass=%d,intf_protocol=%d", intf_nb, intf_class, intf_subclass, intf_protocol); if ((btstack_intf == -1) && intf_class == 0xe0) { btstack_intf = intf_nb; return true; } return false; } /*virtual*/ bool USBHostBTstack::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used { BT_DBG("intf_nb:%d,type:%d,dir:%d",intf_nb, type, dir); if (intf_nb == btstack_intf) { if (ep_int_in == false && type == INTERRUPT_ENDPOINT && dir == IN) { ep_int_in = true; } else if (ep_bulk_in == false && type == BULK_ENDPOINT && dir == IN) { ep_bulk_in = true; } else if (ep_bulk_out == false && type == BULK_ENDPOINT && dir == OUT) { ep_bulk_out = true; } else { return false; } if (ep_int_in && ep_bulk_in && ep_bulk_out) { btstack_device_found = true; } return true; } return false; } int USBHostBTstack::open() { BT_DBG("%p", this); while(!connected()) { if (connect()) { break; } Thread::wait(500); } return 0; } int USBHostBTstack::send_packet(uint8_t packet_type, uint8_t* packet, int size) { USB_TYPE res; switch(packet_type){ case HCI_COMMAND_DATA_PACKET: BT_DBG_BYTES("HCI_CMD:", packet, size); res = host->controlWrite(dev, USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_DEVICE, 0, 0, 0, packet, size); TEST_ASSERT(res == USB_TYPE_OK); break; case HCI_ACL_DATA_PACKET: BT_DBG_BYTES("ACL_SND:", packet, size); res = host->bulkWrite(dev, bulk_out, packet, size); TEST_ASSERT(res == USB_TYPE_OK); break; default: TEST_ASSERT(0); } return 0; } void USBHostBTstack::register_packet_handler(void (*pMethod)(uint8_t, uint8_t*, uint16_t) ) { BT_DBG("pMethod: %p", pMethod); m_pCb = pMethod; } void USBHostBTstack::poll() { osEvent evt = mail_box.get(0); // non-blocking if (evt.status == osEventMail) { Packet* pkt = reinterpret_cast<Packet*>(evt.value.p); TEST_ASSERT(pkt); //BT_DBG("type: %d, buf: %p, len: %d", pkt->type, pkt->buf, pkt->len); if (m_pCb) { m_pCb(pkt->type, pkt->buf, pkt->len); } if (dev) { if (pkt->type == HCI_EVENT_PACKET) { host->interruptRead(dev, int_in, int_report, int_in->getSize(), false); } else { // HCI_ACL_DATA_PACKET host->bulkRead(dev, bulk_in, bulk_report, bulk_in->getSize(), false); } } mail_box.free(pkt); } } void _debug_bytes(const char* pretty, int line, const char* s, uint8_t* buf, int len) { printf("[%s:%d]\n%s", pretty, line, s); for(int i = 0; i < len; i++) { printf(" %02x", buf[i]); } printf("\n"); }