Bläddra i källkod

WIP - Start understanding Bluetooth configuration

WIP - I captured the USB packet information for the startup of a Bluetooth adapter.  I am now in the process of understanding the data that is being sent back and forth and have the device now partially configured.

Nothing works yet!
main
Kurt Eckhardt 6 år sedan
förälder
incheckning
95fc63506e
2 ändrade filer med 297 tillägg och 12 borttagningar
  1. +37
    -1
      USBHost_t36.h
  2. +260
    -11
      bluetooth.cpp

+ 37
- 1
USBHost_t36.h Visa fil

@@ -1543,6 +1543,13 @@ class BluetoothController: public USBDriver {
public:
BluetoothController(USBHost &host) { init(); }
enum {MAX_ENDPOINTS=4, NUM_SERVICES=4}; // Max number of Bluetooth services - if you need more than 4 simply increase this number
/* HCI Events */
enum {EV_INQUIRY_COMPLETE= 0x01,EV_INQUIRY_RESULT= 0x02,EV_CONNECT_COMPLETE= 0x03,EV_INCOMING_CONNECT= 0x04,EV_DISCONNECT_COMPLETE= 0x05
,EV_AUTHENTICATION_COMPLETE= 0x06,EV_REMOTE_NAME_COMPLETE= 0x07,EV_ENCRYPTION_CHANGE= 0x08,EV_CHANGE_CONNECTION_LINK= 0x09,EV_ROLE_CHANGED= 0x12
,EV_NUM_COMPLETE_PKT= 0x13,EV_PIN_CODE_REQUEST= 0x16,EV_LINK_KEY_REQUEST= 0x17,EV_LINK_KEY_NOTIFICATION= 0x18,EV_DATA_BUFFER_OVERFLOW= 0x1A
,EV_MAX_SLOTS_CHANGE= 0x1B,EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE= 0x0C,EV_QOS_SETUP_COMPLETE= 0x0D,EV_COMMAND_COMPLETE= 0x0E,EV_COMMAND_STATUS= 0x0F
,EV_LOOPBACK_COMMAND= 0x19,EV_PAGE_SCAN_REP_MODE= 0x20 };


protected:
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len);
@@ -1557,9 +1564,38 @@ private:

void init();

Pipe_t mypipes[3] __attribute__ ((aligned(32)));
// HCI support functions...
void inline sendHCICommand(uint8_t* data, uint16_t nbytes);
void sendResetHCI();
void sendHCIReadBDAddr();
void sendHCIReadLocalVersionInfo();
void sendHCIReadBufferSize();
void sendHCIReadClassOfDevice();
void sendHCIReadLocalName();
void sendHCIReadVoiceSettings();
void SendHCICommandReadNumberSupportedIAC();
void SendHCICommandReadCurrentIACLAP();
void sendHCIClearAllEventFilters();
void sendHCIWriteConnectionAcceptTimeout();

setup_t setup;
Pipe_t mypipes[4] __attribute__ ((aligned(32)));
Transfer_t mytransfers[7] __attribute__ ((aligned(32)));
strbuf_t mystring_bufs[1];
uint16_t pending_control_ = 0;
uint16_t rx_size_ = 0;
uint16_t rx2_size_ = 0;
uint16_t tx_size_ = 0;
Pipe_t *rxpipe_;
Pipe_t *rx2pipe_;
Pipe_t *txpipe_;
uint8_t rxbuf_[64]; // receive circular buffer
uint8_t rx_packet_data_remaining=0; // how much data remaining
uint8_t rx2buf_[64]; // receive circular buffer
uint8_t txbuf_[64]; // buffer to use to send commands to joystick
uint8_t hciVersion; // what version of HCI do we have?

uint8_t my_bdaddr[6]; // The bluetooth dongles Bluetooth address.

};


+ 260
- 11
bluetooth.cpp Visa fil

@@ -20,7 +20,8 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Note: special thanks to the Linux kernel for the CH341's method of operation, particularly how the baud rate is encoded.
* information about the BlueTooth HCI comes from logic analyzer captures
* plus... http://affon.narod.ru/BT/bluetooth_app_c10.pdf
*/

#include <Arduino.h>
@@ -49,22 +50,84 @@ bool BluetoothController::claim(Device_t *dev, int type, const uint8_t *descript
{
// only claim at device level
println("BluetoothController claim this=", (uint32_t)this, HEX);
print("vid=", dev->idVendor, HEX);
print(", pid=", dev->idProduct, HEX);
print(", bDeviceClass = ", dev->bDeviceClass, HEX);
print(", bDeviceSubClass = ", dev->bDeviceSubClass, HEX);
println(", bDeviceProtocol = ", dev->bDeviceProtocol, HEX);
print_hexbytes(descriptors, len);

// Lets try to support the main USB Bluetooth class...
// http://www.usb.org/developers/defined_class/#BaseClassE0h
if (dev->bDeviceClass != 0xe0) return false; // not base class wireless controller
if ((dev->bDeviceSubClass != 1) || (dev->bDeviceProtocol != 1)) return false; // Bluetooth Programming Interface
if (type != 0) return false;

if (type == 0) {
Serial.printf("BluetoothController claim this=%x vid:pid=%x:%x\n ", (uint32_t)this, dev->idVendor, dev->idProduct);
for (uint8_t i=0; i < len; i++) Serial.printf("%x ", descriptors[i]);
Serial.printf("\n");

// Lets try to process the first Interface and get the end points...
// Some common stuff for both XBoxs
uint32_t count_end_points = descriptors[4];
if (count_end_points < 2) return false;
uint32_t rxep = 0;
uint32_t rx2ep = 0;
uint32_t txep = 0;
uint8_t rx_interval = 0;
uint8_t rx2_interval = 0;
uint8_t tx_interval = 0;
rx_size_ = 0;
rx2_size_ = 0;
tx_size_ = 0;
uint32_t descriptor_index = 9;
while (count_end_points-- && ((rxep == 0) || txep == 0)) {
if (descriptors[descriptor_index] != 7) return false; // length 7
if (descriptors[descriptor_index+1] != 5) return false; // ep desc
if ((descriptors[descriptor_index+4] <= 64)
&& (descriptors[descriptor_index+5] == 0)) {
// have a bulk EP size
if (descriptors[descriptor_index+2] & 0x80 ) {
if (descriptors[descriptor_index+3] == 3) { // Interrupt
rxep = descriptors[descriptor_index+2];
rx_size_ = descriptors[descriptor_index+4];
rx_interval = descriptors[descriptor_index+6];
} else if (descriptors[descriptor_index+3] == 2) { // bulk
rx2ep = descriptors[descriptor_index+2];
rx2_size_ = descriptors[descriptor_index+4];
rx2_interval = descriptors[descriptor_index+6];
}
} else {
txep = descriptors[descriptor_index+2];
tx_size_ = descriptors[descriptor_index+4];
tx_interval = descriptors[descriptor_index+6];
}
}
descriptor_index += 7; // setup to look at next one...
}
if ((rxep == 0) || (txep == 0)) {
Serial.printf("Bluetooth end points not found: %d %d\n", rxep, txep);
return false; // did not find two end points.
}
Serial.printf(" rxep=%d(%d) txep=%d(%d)\n", rxep&15, rx_size_, txep, tx_size_);

print("BluetoothController, rxep=", rxep & 15);
print("(", rx_size_);
print("), txep=", txep);
print("(", tx_size_);
println(")");
rxpipe_ = new_Pipe(dev, 3, rxep & 15, 1, rx_size_, rx_interval);
if (!rxpipe_) return false;
txpipe_ = new_Pipe(dev, 3, txep, 0, tx_size_, tx_interval);
if (!txpipe_) {
//free_Pipe(rxpipe_);
return false;
}
rxpipe_->callback_function = rx_callback;
queue_Data_Transfer(rxpipe_, rxbuf_, rx_size_, this);

txpipe_->callback_function = tx_callback;

return false;
// Send out the reset
device = dev; // yes this is normally done on return from this but should not hurt if we do it here.
sendResetHCI();
pending_control_ = 1; // not sure yet on what we need...

return true;
}


@@ -76,7 +139,12 @@ void BluetoothController::disconnect()

void BluetoothController::control(const Transfer_t *transfer)
{
//println("control callback (bluetooth) ", pending_control, HEX);
println("control callback (bluetooth) ", pending_control_, HEX);
Serial.printf("control callback (bluetooth): %d : ", pending_control_);
uint8_t *buffer = (uint8_t*)transfer->buffer;
for (uint8_t i=0; i < transfer->length; i++) Serial.printf("%x ", buffer[i]);
Serial.printf("\n");

}

/************************************************************/
@@ -98,7 +166,113 @@ void BluetoothController::tx_callback(const Transfer_t *transfer)

void BluetoothController::rx_data(const Transfer_t *transfer)
{
//uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
print_hexbytes((uint8_t*)transfer->buffer, len);
Serial.printf("BT rx_data(%d): ", len);
uint8_t *buffer = (uint8_t*)transfer->buffer;
for (uint8_t i=0; i < len; i++) Serial.printf("%x ", buffer[i]);
Serial.printf("\n");

switch(buffer[0]) { // Switch on event type
case EV_COMMAND_COMPLETE:
if(!buffer[5]) { // Check if command succeeded
Serial.printf(" Command Completed! \n");
break;
}
}

queue_Data_Transfer(rxpipe_, rxbuf_, rx_size_, this);

if (rx_packet_data_remaining == 0) {
rx_packet_data_remaining = buffer[1] + 2; // length of data plus the two bytes at start...
}
rx_packet_data_remaining -= len; // remove the length of this packet from length

switch (pending_control_) {
case 1:
{
static uint8_t HCI_CMD3_10[] = {3, 0x10, 0}; // OCF=3, OGF=4<<2, Parameters=0 ???
sendHCICommand(HCI_CMD3_10, sizeof(HCI_CMD3_10)); // Read local supported features. ?? look up
pending_control_++;
}
break;
case 2:
sendHCIReadLocalVersionInfo();
pending_control_++;
break;
case 3:
hciVersion = buffer[6]; // Should do error checking above...
Serial.printf(" Local Version: %x\n", hciVersion);
sendHCIReadBDAddr();
pending_control_++;
break;
case 4:
Serial.printf(" BD Addr");
for(uint8_t i = 0; i < 6; i++) {
my_bdaddr[i] = buffer[6 + i];
Serial.printf(":%x", my_bdaddr[i]);
}
Serial.printf("\n");
sendHCIReadBufferSize();
pending_control_++;
break;
case 5:
sendHCIReadClassOfDevice();
pending_control_++;
break;
case 6:
sendHCIReadLocalName();
pending_control_++;
break;
case 7:
// received name back... Not sure yet if we received
// full name or just start of it...
Serial.printf(" Local name: ");
for (uint8_t i=6; i < len; i++) {
if (buffer[i] == 0) {
break;
}
Serial.printf("%c", buffer[i]);
}
Serial.printf("\n");
if (rx_packet_data_remaining) {
pending_control_++; // go to next state
} else {
pending_control_ += 2;
sendHCIReadVoiceSettings();
}
break;
case 8:
Serial.printf(" Local name continue: ");
for (uint8_t i=0; i < len; i++) {
if (buffer[i] == 0) {
Serial.printf("\n");
break;
}
Serial.printf("%c", buffer[i]);
}
if (rx_packet_data_remaining == 0) {
sendHCIReadVoiceSettings();
pending_control_++;
}
break;
case 9:
SendHCICommandReadNumberSupportedIAC();
pending_control_++;
break;
case 10:
SendHCICommandReadCurrentIACLAP();
pending_control_++;
break;
case 11:
sendHCIClearAllEventFilters();
pending_control_++;
break;
case 12:
sendHCIWriteConnectionAcceptTimeout();
pending_control_++;
break;
}
}


@@ -106,3 +280,78 @@ void BluetoothController::tx_data(const Transfer_t *transfer)
{
}

void inline BluetoothController::sendHCICommand(uint8_t* data, uint16_t nbytes)
{
mk_setup(setup, 0x20, 0x0, 0, 0, nbytes);
queue_Control_Transfer(device, &setup, data, this);
}

void BluetoothController::sendResetHCI() {
Serial.printf("HCI_RESET called\n");
static uint8_t HCI_RESET[] = {3, 0xc, 0}; // OCF=3, OGF=3<<2, Parameters=0
sendHCICommand(HCI_RESET, sizeof(HCI_RESET));
}

void BluetoothController::sendHCIClearAllEventFilters() {
Serial.printf("HCI_Set_Event_Filter_Clear called\n");
static uint8_t HCI_Set_Event_Filter_Clear[] = {5, 0xc, 1, 0}; // OCF=5, OGF=3<<2, Parameters=1, 0
sendHCICommand(HCI_Set_Event_Filter_Clear, sizeof(HCI_Set_Event_Filter_Clear));
}

void BluetoothController::sendHCIReadLocalName() {
Serial.printf("HCI_Read_Local_Name called\n");
static uint8_t HCI_Read_Local_Name[] = {0x14, 0xc, 0}; // OCF=14, OGF=3<<2, Parameters=0
sendHCICommand(HCI_Read_Local_Name, sizeof(HCI_Read_Local_Name));
}

void BluetoothController::sendHCIWriteConnectionAcceptTimeout() {
// BUGBUG: Hard coded timeout here...
Serial.printf("Write_Connection_Accept_Timeout called\n");
static uint8_t Write_Connection_Accept_Timeout[] = {0x16, 0xc, 2, 0, 0x7d}; // OCF=16, OGF=3<<2, Parameters=2, 0, 7d
sendHCICommand(Write_Connection_Accept_Timeout, sizeof(Write_Connection_Accept_Timeout));

}



void BluetoothController::sendHCIReadClassOfDevice() {
Serial.printf("HCI_READ_CLASS_OF_DEVICE called\n");
static uint8_t HCI_READ_CLASS_OF_DEVICE[] = {0x23, 0xc, 0}; // OCF=23, OGF=3<<2, Parameters=0
sendHCICommand(HCI_READ_CLASS_OF_DEVICE, sizeof(HCI_READ_CLASS_OF_DEVICE));
}

void BluetoothController::sendHCIReadVoiceSettings() {
Serial.printf("HCI_Read_Voice_Setting called\n");
static uint8_t HCI_Read_Voice_Setting[] = {0x25, 0xc, 0}; // OCF=25, OGF=3<<2, Parameters=0
sendHCICommand(HCI_Read_Voice_Setting, sizeof(HCI_Read_Voice_Setting));
}

void BluetoothController::SendHCICommandReadNumberSupportedIAC() {
Serial.printf("HCI_Read_Number_Of_Supported_IAC\n");
static uint8_t HCI_Read_Number_Of_Supported_IAC[] = {0x38, 0xc, 0}; // OCF=38, OGF=3<<2, Parameters=0
sendHCICommand(HCI_Read_Number_Of_Supported_IAC, sizeof(HCI_Read_Number_Of_Supported_IAC));
}

void BluetoothController::SendHCICommandReadCurrentIACLAP() {
Serial.printf("HCI_Read_Current_IAC_LAP called\n");
static uint8_t HCI_Read_Current_IAC_LAP[] = {0x39, 0xc, 0}; // OCF=39, OGF=3<<2, Parameters=0
sendHCICommand(HCI_Read_Current_IAC_LAP, sizeof(HCI_Read_Current_IAC_LAP));
}


void BluetoothController::sendHCIReadBufferSize() {
Serial.printf("HCI_Read_Buffer_Size called\n");
static uint8_t HCI_Read_Buffer_Size[] = {5, 0x10, 0}; // OCF=5, OGF=4<<2, Parameters=0 ???
sendHCICommand(HCI_Read_Buffer_Size, sizeof(HCI_Read_Buffer_Size));
}
void BluetoothController::sendHCIReadBDAddr() {
Serial.printf("HCI_Read_BD_ADDR called\n");
static uint8_t HCI_Read_BD_ADDR[] = {9, 0x10, 0}; // OCF=9, OGF=4<<2, Parameters=0 ???
sendHCICommand(HCI_Read_BD_ADDR, sizeof(HCI_Read_BD_ADDR));
}

void BluetoothController::sendHCIReadLocalVersionInfo() {
Serial.printf("HCI_Read_Local_Version_Information called\n");
static uint8_t HCI_Read_Local_Version_Information[] = {1, 0x10, 0}; // OCF=1, OGF=4<<2, Parameters=0 ???
sendHCICommand(HCI_Read_Local_Version_Information, sizeof(HCI_Read_Local_Version_Information));
}

Laddar…
Avbryt
Spara