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.
Dependencies: FatFileSystem TB6612FNG2 mbed
usbbt/usbbt.cpp
- Committer:
- mbed_Cookbook_SE
- Date:
- 2015-11-30
- Revision:
- 0:de03cbbcd0ff
File content as of revision 0:de03cbbcd0ff:
#include "usbbt.h"
//#define __DEBUG
#include "mydbg.h"
#include "Utils.h"
usbbt::usbbt(int dongle)
: m_dongle(dongle),m_pEpIntIn(NULL),m_pEpBulkIn(NULL),m_pEpBulkOut(NULL),
m_int_seq(0),m_bulk_seq(0)
{
}
int usbbt::setup(int timeout)
{
for(int i = 0; i < 2; i++) {
m_pDev = m_pHost->getDeviceByClass(0xe0, m_dongle);
if (m_pDev || i > 0) {
break;
}
UsbErr rc = Usb_poll();
if (rc == USBERR_PROCESSING) {
VERBOSE("%p USBERR_PROCESSING\n", this);
return -1;
}
}
DBG("m_pDev=%p\n", m_pDev);
if (m_pDev == NULL) {
VERBOSE("%p Bluetooth dongle(%d) NOT FOUND\n", this, m_dongle);
return -1;
}
DBG_ASSERT(m_pDev);
ParseConfiguration();
return 0;
}
int usbbt::ParseConfiguration()
{
UsbErr rc;
uint8_t ConfigDesc[9];
int index = 0;
DBG_ASSERT(m_pDev);
rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, ConfigDesc, sizeof(ConfigDesc));
DBG_ASSERT(rc == USBERR_OK);
DBG_BYTES("ConfigDescriptor 9bytes", ConfigDesc, sizeof(ConfigDesc));
DBG_ASSERT(ConfigDesc[0] == 9);
DBG_ASSERT(ConfigDesc[1] == 0x02);
int wTotalLength = *((uint16_t*)&ConfigDesc[2]);
DBG("TotalLength: %d\n", wTotalLength);
int bConfigValue = ConfigDesc[5];
DBG_ASSERT(bConfigValue == 1);
DBG("ConfigValue: %d\n", bConfigValue);
VERBOSE("MaxPower: %d mA\n", ConfigDesc[8]*2);
uint8_t* buf = new uint8_t[wTotalLength];
DBG_ASSERT(buf);
rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, wTotalLength);
DBG_ASSERT(rc == USBERR_OK);
DBG_ASSERT(ConfigDesc[1] == 0x02);
for (int pos = 0; pos < wTotalLength; pos += buf[pos]) {
DBG_BYTES("CFG", buf+pos, buf[pos]);
int type = buf[pos+1];
if (USB_DESCRIPTOR_TYPE_INTERFACE == type) { // 0x04
DBG("InterfaceNumber: %d\n", buf[pos+2]);
DBG("AlternateSetting: %d\n", buf[pos+3]);
DBG("NumEndpoint: %d\n", buf[pos+4]);
VERBOSE("InterfaceClass: %02X\n", buf[pos+5]);
VERBOSE("InterfaceSubClass: %02X\n", buf[pos+6]);
VERBOSE("InterfaceProtocol: %02X\n", buf[pos+7]);
DBG_ASSERT(buf[pos+6] == 0x01);
DBG_ASSERT(buf[pos+7] == 0x01);
}
if (USB_DESCRIPTOR_TYPE_ENDPOINT == type) {
DBG_ASSERT(buf[pos] == 7);
uint8_t att = buf[pos+3];
uint8_t ep = buf[pos+2];
bool dir = ep & 0x80; // true=IN
uint16_t size = LE16(buf+pos+4);
DBG("EndpointAddress: %02X\n", ep);
DBG("Attribute: %02X\n", att);
DBG("MaxPacketSize: %d\n", size);
UsbEndpoint* pEp = new UsbEndpoint(m_pDev, ep, dir, att == 3 ? USB_INT : USB_BULK, size);
DBG_ASSERT(pEp);
if (att == 3) { // interrupt
if (m_pEpIntIn == NULL) {
m_pEpIntIn = pEp;
}
} else if (att == 2) { // bulk
if (dir) {
if (m_pEpBulkIn == NULL) {
m_pEpBulkIn = pEp;
}
} else {
if (m_pEpBulkOut == NULL) {
m_pEpBulkOut = pEp;
}
}
}
}
if (m_pEpIntIn && m_pEpBulkIn && m_pEpBulkOut) { // cut off
break;
}
}
delete[] buf;
DBG_ASSERT(m_pEpIntIn);
DBG_ASSERT(m_pEpBulkIn);
DBG_ASSERT(m_pEpBulkOut);
return 0;
}
int usbbt::send_packet(uint8_t packet_type, uint8_t* packet, int size)
{
//DBG("\npacket_type=%d\n", packet_type);
//DBG_HEX(packet, size);
int rc;
switch(packet_type){
case HCI_COMMAND_DATA_PACKET:
DBG_ASSERT(m_pDev);
DBG_BYTES("\nCMD", packet, size);
rc = m_pDev->controlSend(
USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_DEVICE,
0, 0, 0, packet, size);
DBG_ASSERT(rc == USBERR_OK);
return 0;
case HCI_ACL_DATA_PACKET:
DBG_ASSERT(m_pEpBulkOut);
DBG_BYTES("\nACL", packet, size);
rc = m_pEpBulkOut->transfer(packet, size);
DBG_ASSERT(rc == USBERR_PROCESSING);
while(m_pEpBulkOut->status() == USBERR_PROCESSING){
wait_us(1);
}
return 0;
default:
DBG_ASSERT(0);
return -1;
}
}
void usbbt::poll()
{
//DBG("m_int_seq=%d\n", m_int_seq);
int rc, len;
switch(m_int_seq) {
case 0:
m_int_seq++;
break;
case 1:
rc = m_pEpIntIn->transfer(m_int_buf, sizeof(m_int_buf));
DBG_ASSERT(rc == USBERR_PROCESSING);
m_int_seq++;
break;
case 2:
len = m_pEpIntIn->status();
if (len == USBERR_PROCESSING) {
break;
}
if (len >= 0) {
//DBG("len=%d\n", len);
//DBG_HEX(m_int_buf, len);
onPacket(HCI_EVENT_PACKET, m_int_buf, len);
m_int_seq = 0;
break;
}
DBG_ASSERT(0);
break;
}
switch(m_bulk_seq) {
case 0:
m_bulk_seq++;
break;
case 1:
rc = m_pEpBulkIn->transfer(m_bulk_buf, sizeof(m_bulk_buf));
DBG_ASSERT(rc == USBERR_PROCESSING);
m_bulk_seq++;
break;
case 2:
len = m_pEpBulkIn->status();
if (len == USBERR_PROCESSING) {
break;
}
if (len >= 0) {
//DBG("len=%d\n", len);
//DBG_HEX(m_bulk_buf, len);
onPacket(HCI_ACL_DATA_PACKET, m_bulk_buf, len);
m_bulk_seq = 0;
break;
}
DBG_ASSERT(0);
break;
}
}
void usbbt::onPacket(uint8_t packet_type, uint8_t* packet, uint16_t size)
{
DBG("\npacket_type=%d packet=%p size=%d\n", packet_type, packet, size);
DBG_HEX(packet, size);
if(m_pCbItem && m_pCbMeth)
(m_pCbItem->*m_pCbMeth)(packet_type, packet, size);
else if(m_pCb)
m_pCb(packet_type, packet, size);
}
void usbbt::setOnPacket( void (*pMethod)(uint8_t, uint8_t*, uint16_t) )
{
m_pCb = pMethod;
m_pCbItem = NULL;
m_pCbMeth = NULL;
}
void usbbt::clearOnPacket()
{
m_pCb = NULL;
m_pCbItem = NULL;
m_pCbMeth = NULL;
}