ソースを参照

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年前
コミット
95fc63506e
2個のファイルの変更297行の追加12行の削除
  1. +37
    -1
      USBHost_t36.h
  2. +260
    -11
      bluetooth.cpp

+ 37
- 1
USBHost_t36.h ファイルの表示

@@ -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 ファイルの表示

@@ -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));
}

読み込み中…
キャンセル
保存