Based on Peter Barrett\'s work on BlueUSB, I added support for the PS3 Sixaxis controller (both USB and Bluetooth). When connecting a Sixaxis via USB, it will be paired with the (hardcoded) MAC address of my Bluetooth dongle.
Dependents: PS3_BlueUSB_downstate
hci.cpp
00001 /* 00002 Copyright (c) 2010 Peter Barrett 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 */ 00022 00023 /* 00024 Tue Apr 26 2011 Bart Janssens: added HCI connection accept 00025 */ 00026 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 #include <stdio.h> 00030 #include <string.h> 00031 00032 #include "Utils.h" 00033 #include "hci.h" 00034 #include "hci_private.h" 00035 00036 enum hci_callback_evt 00037 { 00038 NONE, 00039 CONNECT, 00040 DISCONECT, 00041 INQUIRYRESULT 00042 }; 00043 00044 #define MAX_BLUETOOTH_ADAPTERS 1 00045 00046 enum StateMask { 00047 MASK_RESET = 1, 00048 MASK_READ_BUFFER_SIZE = 2, 00049 MASK_READ_BD_ADDR = 4, 00050 MASK_INITED = 8, 00051 MASK_INQUIRY = 16, 00052 MASK_REMOTE_NAME = 32, 00053 MASK_CREATE_CONNECTION = 64 00054 }; 00055 00056 int HCI::Open(HCITransport* transport, HCICallback callback) 00057 { 00058 _transport = transport; 00059 _transport->Set(this); 00060 _callback = callback; 00061 _state = 0; 00062 for (int i = 0; i < MAX_BTDEVICES; i++) 00063 { 00064 _devices[i].Init(); 00065 _devices[i]._transport = transport; 00066 } 00067 return SendCmd(HCI_OP_RESET); 00068 } 00069 00070 void printf(const BD_ADDR* addr); 00071 00072 BTDevice* HCI::Find(const BD_ADDR* addr) 00073 { 00074 for (int i = 0; i < MAX_BTDEVICES; i++) 00075 if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0) 00076 return &_devices[i]; 00077 return 0; 00078 } 00079 00080 BTDevice* HCI::Find(int handle) 00081 { 00082 for (int i = 0; i < MAX_BTDEVICES; i++) 00083 if (_devices[i]._state != 0 && handle == _devices[i]._handle) 00084 return &_devices[i]; 00085 return 0; 00086 } 00087 // 00088 bool HCI::Busy() 00089 { 00090 return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0; 00091 } 00092 00093 int HCI::Inquiry(int duration) 00094 { 00095 _state |= MASK_INQUIRY; 00096 u8 buf[5]; 00097 buf[0] = 0x33; 00098 buf[1] = 0x8B; 00099 buf[2] = 0x9E; 00100 buf[3] = duration; 00101 buf[4] = 5; // 5 results 00102 SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf)); 00103 return 0; 00104 } 00105 00106 int HCI::WriteScanEnable() 00107 { 00108 00109 u8 buf[2]; 00110 buf[0] = 0x03; 00111 buf[1] = 0x01; 00112 00113 SendCmd(HCI_OP_WRITE_SCAN_ENABLE,buf,sizeof(buf)); 00114 return 0; 00115 } 00116 00117 int HCI::AcceptConnection(const BD_ADDR* addr) 00118 { 00119 u8 buf[6+4]; 00120 memset(buf,0,sizeof(buf)); 00121 memcpy(buf,addr,6); 00122 buf[7] = 0; 00123 00124 SendCmd(HCI_OP_ACCEPT_CONN_REQ,buf,sizeof(buf)); 00125 return 0; 00126 } 00127 00128 int HCI::SendCmd(int cmd, const u8* params, int len) 00129 { 00130 u8 b[32]; 00131 b[0] = cmd; 00132 b[1] = (cmd >> 8); 00133 b[2] = len; 00134 if (params) 00135 memcpy(b+3,params,len); 00136 _transport->HCISend(b,len+3); 00137 return 0; 00138 } 00139 00140 void HCI::OnCommandComplete(int cmd, const u8* data, int len) 00141 { 00142 // printf("%04X %s",cmd,CmdStr(cmd)); 00143 if (len < 0) 00144 return; 00145 //printfBytes(" complete",data,min(16,len)); 00146 00147 switch (cmd) 00148 { 00149 // Init phase 0 00150 case HCI_OP_RESET: // Reset done, init chain to HCI_OP_READ_LOCAL_NAME 00151 SendCmd(HCI_OP_READ_BUFFER_SIZE); 00152 _state |= MASK_RESET; 00153 break; 00154 00155 // Init phase 1 00156 case HCI_OP_READ_BUFFER_SIZE: 00157 _acl_mtu = LE16(data); 00158 _sco_mtu = data[2]; 00159 _acl_max_pkt = LE16(data+3); 00160 _sco_max_pkt = LE16(data+5); 00161 SendCmd(HCI_OP_READ_BD_ADDR); 00162 _state |= MASK_READ_BUFFER_SIZE; 00163 break; 00164 00165 // Init phase 2 00166 case HCI_OP_READ_BD_ADDR: 00167 _localAddr = *((BD_ADDR*)data); // Local Address 00168 printf("Local Address: "); 00169 printf(&_localAddr); 00170 printf("\r\n"); 00171 00172 _state |= MASK_READ_BD_ADDR; 00173 _state |= MASK_INITED; 00174 Callback(CALLBACK_READY,data,6); 00175 break; 00176 00177 // 0CXX 00178 case HCI_OP_READ_LOCAL_NAME: 00179 break; 00180 00181 case HCI_OP_READ_LOCAL_VERSION: 00182 // params 00183 //SendCmd(HCI_OP_READ_LOCAL_NAME); 00184 break; 00185 00186 case HCI_OP_READ_LOCAL_COMMANDS: 00187 break; 00188 00189 case HCI_OP_READ_LOCAL_FEATURES: 00190 //SendCmd(HCI_OP_READ_LOCAL_VERSION); 00191 break; 00192 00193 case HCI_OP_READ_LOCAL_EXT_FEATURES: 00194 break; 00195 00196 case HCI_OP_PIN_CODE_REPLY: 00197 printf("Got pin reply\r\n"); 00198 break; 00199 00200 default: 00201 //printf("Unrecognized Command %04X\r\n",cmd); 00202 break; 00203 } 00204 } 00205 00206 void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len) 00207 { 00208 _callback(this,c,data,len); 00209 } 00210 00211 int HCI::RemoteNameRequest(const BD_ADDR* addr) 00212 { 00213 _state |= MASK_REMOTE_NAME; 00214 u8 buf[6+4]; 00215 memset(buf,0,sizeof(buf)); 00216 memcpy(buf,addr,6); 00217 buf[7] = 1; 00218 return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf)); 00219 } 00220 00221 int HCI::CreateConnection(const BD_ADDR* remoteAddr) 00222 { 00223 _state |= MASK_CREATE_CONNECTION; 00224 u8 buf[6+7]; 00225 memset(buf,0,sizeof(buf)); 00226 memcpy(buf,remoteAddr,6); 00227 buf[6] = 0x18; // DM1,DH1 00228 buf[7] = 0xCC; // DM3, DH3, DM5, DH5 00229 buf[8] = 1; // Page Repetition R1 00230 return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf)); 00231 } 00232 00233 int HCI::Disconnect(const BD_ADDR* bdaddr) 00234 { 00235 BTDevice* d = Find(bdaddr); 00236 if (!d) 00237 return ERR_HCI_DEVICE_NOT_FOUND; 00238 int handle = d->_handle; 00239 printf("Disconnect from %d\r\n",handle); 00240 _state |= MASK_CREATE_CONNECTION; 00241 u8 buf[3]; 00242 buf[0] = handle; 00243 buf[1] = (handle >> 8); 00244 buf[2] = 0x13; 00245 return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf)); 00246 } 00247 00248 void HCI::DisconnectComplete(int handle) 00249 { 00250 BTDevice* d = Find(handle); 00251 if (!d) 00252 return; 00253 d->_handle = 0; 00254 } 00255 00256 int HCI::DisconnectAll() 00257 { 00258 BTDevice* devs[8]; 00259 int count = GetDevices(devs,8); 00260 for (int i = 0; i < count; i++) 00261 Disconnect(&devs[i]->_info.bdaddr); 00262 return 0; 00263 } 00264 00265 int HCI::PinCodeReply(const u8* data) 00266 { 00267 u8 b[6+1+16]; 00268 memset(b,0,sizeof(b)); 00269 memcpy(b,data,6); 00270 b[6] = 4; 00271 b[7] = '0'; 00272 b[8] = '0'; 00273 b[9] = '0'; 00274 b[10] = '0'; 00275 return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b)); 00276 } 00277 00278 void HCI::InquiryResult(const inquiry_info* info) 00279 { 00280 BTDevice* bt = Find(&info->bdaddr); 00281 if (!bt) // new device 00282 { 00283 for (int i = 0; i < MAX_BTDEVICES; i++) 00284 { 00285 if (_devices[i]._state == 0) 00286 { 00287 bt = _devices + i; 00288 bt->_state = 1; 00289 break; 00290 } 00291 } 00292 if (!bt) 00293 { 00294 printf("HCI::InquiryResult too many devices\r\n"); 00295 return; // Too many devices! 00296 } 00297 } 00298 00299 bt->_info = *info; 00300 } 00301 00302 int HCI::GetDevices(BTDevice** devices, int maxDevices) 00303 { 00304 int j = 0; 00305 for (int i = 0; i < MAX_BTDEVICES; i++) 00306 { 00307 if (_devices[i]._state != 0) 00308 { 00309 devices[j++] = _devices + i; 00310 if (j == maxDevices) 00311 break; 00312 } 00313 } 00314 return j; 00315 } 00316 00317 void HCI::RemoteName(const BD_ADDR* addr, const char* name) 00318 { 00319 BTDevice* d = Find(addr); 00320 if (d) 00321 { 00322 strncpy(d->_name,name,sizeof(d->_name)-1); 00323 d->_name[sizeof(d->_name)-1] = 0; 00324 } 00325 } 00326 00327 void HCI::ConnectComplete(const connection_info* info) 00328 { 00329 BTDevice* d = Find(&info->bdaddr); 00330 if (!d) 00331 return; 00332 if (info->status == 0) 00333 { 00334 d->_handle = info->handle; 00335 printf("Connected on %04X\r\n",info->handle); 00336 } else 00337 printf("Connection failed with %d\r\n",info->status); 00338 } 00339 00340 void HCI::ConnectRequest(const request_info* info) 00341 { 00342 BTDevice* bt = Find(&info->bdaddr); 00343 if (!bt) // new device 00344 { 00345 for (int i = 0; i < MAX_BTDEVICES; i++) 00346 { 00347 if (_devices[i]._state == 0) 00348 { 00349 bt = _devices + i; 00350 bt->_state = 1; 00351 break; 00352 } 00353 } 00354 if (!bt) 00355 { 00356 printf("HCI::ConnectRequest too many devices\r\n"); 00357 return; // Too many devices! 00358 } 00359 } 00360 bt->_info.bdaddr = info->bdaddr; 00361 memcpy(bt->_info.dev_class,info->dev_class,3); 00362 AcceptConnection(&info->bdaddr); 00363 } 00364 00365 void HCI::HCIRecv(const u8* data, int len) 00366 { 00367 //printfBytes(EvtStr(data[0]),data,len); 00368 //printfBytes(EvtStr(data[0]),data,min(len,16)); 00369 //printf("HCI Event %02X\r\n",data[0]); 00370 switch (data[0]) 00371 { 00372 case HCI_EV_INQUIRY_COMPLETE: 00373 printfBytes("Inquiry Complete",data,data[1]); 00374 _state &= ~MASK_INQUIRY; 00375 Callback(CALLBACK_INQUIRY_DONE,0,0); 00376 WriteScanEnable(); 00377 break; 00378 00379 case HCI_EV_INQUIRY_RESULT: 00380 { 00381 const u8* end = data[1] + data + 2; 00382 data += 3; 00383 while (data < end) 00384 { 00385 inquiry_info align; 00386 memcpy(&align,data,sizeof(inquiry_info)); 00387 InquiryResult(&align); 00388 Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info)); 00389 data += 14; 00390 } 00391 } 00392 break; 00393 00394 case HCI_EV_CONN_COMPLETE: 00395 _state &= ~MASK_CREATE_CONNECTION; 00396 { 00397 connection_info align; 00398 memcpy(&align,data+2,sizeof(connection_info)); 00399 ConnectComplete(&align); 00400 Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info)); 00401 } 00402 break; 00403 00404 case HCI_EV_CONN_REQUEST: 00405 { 00406 request_info align; 00407 memcpy(&align,data+2,sizeof(request_info)); 00408 ConnectRequest(&align); 00409 } 00410 break; 00411 00412 case HCI_EV_DISCONN_COMPLETE: 00413 DisconnectComplete(LE16(data+3)); 00414 break; 00415 00416 case HCI_EV_REMOTE_NAME: 00417 { 00418 BD_ADDR* addr = (BD_ADDR*)(data+3); 00419 const char* name = (const char*)(data + 9); 00420 RemoteName(addr,name); 00421 } 00422 Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1)); // addr is in here too 00423 _state &= ~MASK_REMOTE_NAME; 00424 break; 00425 00426 case HCI_EV_CMD_STATUS: 00427 { 00428 const char* errs = HCIErrStr(data[2]); 00429 printf("Status %s %s\r\n",CmdStr(LE16(data+4)),errs); 00430 } 00431 break; 00432 00433 case HCI_EV_CMD_COMPLETE: 00434 OnCommandComplete(data[3] | (data[4] << 8),data+6,data[1]-4); 00435 break; 00436 00437 case HCI_EV_PIN_CODE_REQ: 00438 PinCodeReply(data+2); 00439 break; 00440 00441 case HCI_EV_LINK_KEY_REQ: 00442 SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6); 00443 break; 00444 00445 default: 00446 ; 00447 // printfBytes("HCI Event:",data,data[1]+2); 00448 } 00449 } 00450 00451 int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr) 00452 { 00453 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00454 L2CAPAddr* l2capaddr = (L2CAPAddr*)addr; 00455 BTDevice* bt = Find(&l2capaddr->bdaddr); 00456 if (!bt) 00457 { 00458 printf("Can't open l2cap %d on ",l2capaddr->psm); 00459 printf(&l2capaddr->bdaddr); 00460 printf("\r\n"); 00461 return ERR_HCI_DEVICE_NOT_FOUND; 00462 } 00463 l2capsock->btdevice = bt; 00464 return bt->Open(sock,addr); 00465 } 00466 00467 int HCI::Create(SocketInternal* sock, SocketAddrHdr* addr) 00468 { 00469 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00470 L2CAPAddr* l2capaddr = (L2CAPAddr*)addr; 00471 BTDevice* bt = Find(&l2capaddr->bdaddr); 00472 if (!bt) 00473 { 00474 printf("HCI Create: Can't open l2cap on "); 00475 printf(&l2capaddr->bdaddr); 00476 printf("\r\n"); 00477 return ERR_HCI_DEVICE_NOT_FOUND; 00478 } 00479 l2capsock->btdevice = bt; 00480 //return 0; 00481 return bt->Create(sock,addr); 00482 } 00483 00484 00485 int HCI::Accept(SocketInternal* sock, SocketAddrHdr* addr) 00486 { 00487 00488 printf("Call to HCI Accept \r\n"); 00489 00490 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00491 L2CAPAddr* l2capaddr = (L2CAPAddr*)addr; 00492 BTDevice* bt = Find(&l2capaddr->bdaddr); 00493 if (!bt) 00494 { 00495 //printf("Can't open l2cap %d on ",l2capaddr->psm); 00496 printf("HCI Accept: Can't open l2cap on "); 00497 printf(&l2capaddr->bdaddr); 00498 printf("\r\n"); 00499 return ERR_HCI_DEVICE_NOT_FOUND; 00500 } 00501 //l2capsock->btdevice = bt; 00502 return bt->Open(sock,addr); 00503 00504 } 00505 00506 /** 00507 SocketInternal* HCI::Create(SocketInternal* sock) 00508 { 00509 return sock; 00510 } 00511 **/ 00512 00513 00514 int HCI::Send(SocketInternal* sock, const u8* data, int len) 00515 { 00516 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00517 return l2capsock->btdevice->Send(sock,data,len); // Pointless double dispatch 00518 } 00519 00520 int HCI::Close(SocketInternal* sock) 00521 { 00522 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00523 return l2capsock->btdevice->Close(sock); // Pointless double dispatch 00524 } 00525 00526 void HCI::ACLRecv(const u8* data, int len) 00527 { 00528 int handle = LE16(data); 00529 BD_ADDR* addr; 00530 BTDevice* d = Find(handle & 0x0FFF); 00531 addr = &d->_info.bdaddr; 00532 00533 if (d) 00534 d->ACLRecv(addr,data,len); 00535 } 00536 00537 //=================================================================== 00538 //===================================================================
Generated on Fri Jul 22 2022 14:50:38 by 1.7.2