mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-31 18:33:00 +00:00
Added RFCOMM
This commit is contained in:
parent
3c4d4b9093
commit
e115bf24db
11
TODO.txt
11
TODO.txt
@ -18,8 +18,11 @@
|
||||
- removed link key and name caching from BTstackManager, honor BTSTACK_EVENT_REMOTE_NAME_CACHED
|
||||
- Retina icons!
|
||||
|
||||
NEXT:
|
||||
- create Retina status bar icons
|
||||
2011-03-xx: Release 0.3 - RFCOMM for Celeste and others
|
||||
- use posix run loop for daemon again - fixes issues with lost bytes on Bluetooth UART
|
||||
- fixes for cocoa run loop implemenation
|
||||
- move RFCOMM code into BTdaemon
|
||||
- Darwin notification on BTdaemon start/stop
|
||||
|
||||
AFTER:
|
||||
- fix broken host detection in configure.in (make it compile on linux)
|
||||
@ -40,8 +43,6 @@ AFTER:
|
||||
- decide on configure flags
|
||||
- dynamic link BTdaemon against libBTstack.dylist
|
||||
|
||||
- move RFCOMM code into BTdaemon
|
||||
|
||||
- HCI CMD packet is limited to 1024 bytes payload. SDP records could be larger than that. Options:
|
||||
- provide a way to transfer SDP records in segments
|
||||
- ignore HCI command lenght on socket connection and directly stream data without buffer
|
||||
@ -82,7 +83,7 @@ AFTER:
|
||||
* use deleteRowsAtIndexPaths:withRowAnimation: to remove them-
|
||||
|
||||
== Refactor/Improve Architecture ==
|
||||
- add linked_list_iterator that can remove elements (used by l2cap_close_connection and sdp_unregister_services_for_connection
|
||||
- add linked_list_iterator that can remove elements (used by l2cap_close_connection and sdp_unregister_services_for_connection)
|
||||
- clean up control flow
|
||||
- l2cap directly sends data over socket: good/bad?
|
||||
- split daemon into stack parts
|
||||
|
@ -238,6 +238,7 @@ if test "x$USE_COCOA_RUN_LOOP" = xyes; then
|
||||
fi
|
||||
echo "#define USE_POSIX_RUN_LOOP" >> config.h
|
||||
echo "#define HAVE_SDP" >> config.h
|
||||
echo "#define HAVE_RFCOMM" >> config.h
|
||||
if test ! -z "$REMOTE_DEVICE_DB" ; then
|
||||
echo "#define REMOTE_DEVICE_DB $REMOTE_DEVICE_DB" >> config.h
|
||||
fi
|
||||
|
@ -2,8 +2,6 @@
|
||||
# http://bit.ly/af0Evu
|
||||
# http://hwtt.net/ths
|
||||
|
||||
export TARGET_STRIP_FLAGS=
|
||||
|
||||
include $(THEOS)/makefiles/common.mk
|
||||
|
||||
APPLICATION_NAME = WiiMoteOpenGLDemo
|
||||
@ -13,6 +11,6 @@ WiiMoteOpenGLDemo_FILES += ../../CocoaTouch/src/BTstackManager.m ../../CocoaTouc
|
||||
WiiMoteOpenGLDemo_CFLAGS = -I . -I Classes -I ../../include -I ../../CocoaTouch/include
|
||||
WiiMoteOpenGLDemo_LDFLAGS = -L../../src -lbtstack
|
||||
WiiMoteOpenGLDemo_FRAMEWORKS = Foundation UIKit CoreGraphics OpenGLES QuartzCore
|
||||
WiiMoteOpenGLDemo_RESOURCE_FILES = wiimote_logo_55px.png wiimote_texture.png Info.plist
|
||||
WiiMoteOpenGLDemo_RESOURCE_FILES = wiimote_logo_55px.png wiimote_texture.png
|
||||
|
||||
include $(FW_MAKEDIR)/application.mk
|
||||
|
@ -11,10 +11,11 @@
|
||||
1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
|
||||
9C0D06391091035200FC3BBA /* BTDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C0D06361091035200FC3BBA /* BTDevice.m */; };
|
||||
9C0D070D1092316D00FC3BBA /* EAGLViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C0D070C1092316D00FC3BBA /* EAGLViewController.m */; };
|
||||
9C5E121612DE55B80013EF2C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C5E121512DE55B80013EF2C /* Foundation.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
9C5E127112DE59E30013EF2C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C5E127012DE59E30013EF2C /* UIKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
9C5E127312DE59EB0013EF2C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C5E127212DE59EB0013EF2C /* CoreGraphics.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
9C5E127712DE59FA0013EF2C /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C5E127612DE59FA0013EF2C /* OpenGLES.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
9C5E139612DE6C7B0013EF2C /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C5E139512DE6C7B0013EF2C /* OpenGLES.framework */; };
|
||||
9C5E139A12DE6C8A0013EF2C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C5E139912DE6C8A0013EF2C /* CoreGraphics.framework */; };
|
||||
9C5E139E12DE6C960013EF2C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C5E139D12DE6C960013EF2C /* UIKit.framework */; };
|
||||
9C5E13A212DE6CAA0013EF2C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C5E13A112DE6CAA0013EF2C /* CoreFoundation.framework */; };
|
||||
9C5E13A812DE6CB30013EF2C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C5E13A712DE6CB30013EF2C /* Foundation.framework */; };
|
||||
9C6BB62E1027911E00A0BCB0 /* wiimote_texture.png in Resources */ = {isa = PBXBuildFile; fileRef = 9C6BB62D1027911E00A0BCB0 /* wiimote_texture.png */; };
|
||||
9C8B71C712DBB9FE00E3FD8A /* BTstackManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C8B71C412DBB9FE00E3FD8A /* BTstackManager.m */; };
|
||||
9C8B71C812DBB9FE00E3FD8A /* BTDiscoveryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C8B71C612DBB9FE00E3FD8A /* BTDiscoveryViewController.m */; };
|
||||
@ -42,10 +43,11 @@
|
||||
9C18001D108B94FB00824BE7 /* linked_list.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = linked_list.h; sourceTree = "<group>"; };
|
||||
9C18001E108B94FB00824BE7 /* run_loop.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = run_loop.h; sourceTree = "<group>"; };
|
||||
9C18001F108B94FB00824BE7 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
|
||||
9C5E121512DE55B80013EF2C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
9C5E127012DE59E30013EF2C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
9C5E127212DE59EB0013EF2C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
9C5E127612DE59FA0013EF2C /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
|
||||
9C5E139512DE6C7B0013EF2C /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
|
||||
9C5E139912DE6C8A0013EF2C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
9C5E139D12DE6C960013EF2C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
9C5E13A112DE6CAA0013EF2C /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||
9C5E13A712DE6CB30013EF2C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
9C6BB62D1027911E00A0BCB0 /* wiimote_texture.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wiimote_texture.png; sourceTree = "<group>"; };
|
||||
9C8B71C312DBB9FE00E3FD8A /* BTstackManager.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = BTstackManager.h; path = ../../CocoaTouch/include/BTstack/BTstackManager.h; sourceTree = SOURCE_ROOT; };
|
||||
9C8B71C412DBB9FE00E3FD8A /* BTstackManager.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; name = BTstackManager.m; path = ../../CocoaTouch/src/BTstackManager.m; sourceTree = SOURCE_ROOT; };
|
||||
@ -62,10 +64,11 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9CD1C867117E2F6900C7A4F4 /* libBTstack.dylib in Frameworks */,
|
||||
9C5E121612DE55B80013EF2C /* Foundation.framework in Frameworks */,
|
||||
9C5E127112DE59E30013EF2C /* UIKit.framework in Frameworks */,
|
||||
9C5E127312DE59EB0013EF2C /* CoreGraphics.framework in Frameworks */,
|
||||
9C5E127712DE59FA0013EF2C /* OpenGLES.framework in Frameworks */,
|
||||
9C5E139612DE6C7B0013EF2C /* OpenGLES.framework in Frameworks */,
|
||||
9C5E139A12DE6C8A0013EF2C /* CoreGraphics.framework in Frameworks */,
|
||||
9C5E139E12DE6C960013EF2C /* UIKit.framework in Frameworks */,
|
||||
9C5E13A212DE6CAA0013EF2C /* CoreFoundation.framework in Frameworks */,
|
||||
9C5E13A812DE6CB30013EF2C /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -131,10 +134,11 @@
|
||||
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9C5E121512DE55B80013EF2C /* Foundation.framework */,
|
||||
9C5E127012DE59E30013EF2C /* UIKit.framework */,
|
||||
9C5E127212DE59EB0013EF2C /* CoreGraphics.framework */,
|
||||
9C5E127612DE59FA0013EF2C /* OpenGLES.framework */,
|
||||
9C5E139512DE6C7B0013EF2C /* OpenGLES.framework */,
|
||||
9C5E139912DE6C8A0013EF2C /* CoreGraphics.framework */,
|
||||
9C5E139D12DE6C960013EF2C /* UIKit.framework */,
|
||||
9C5E13A112DE6CAA0013EF2C /* CoreFoundation.framework */,
|
||||
9C5E13A712DE6CB30013EF2C /* Foundation.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@ -279,8 +283,9 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Milanka Ringwald (Y4MWH89GZ9)";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Don't Code Sign";
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_VERSION = 4.2;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@ -294,8 +299,7 @@
|
||||
"-lbtstack",
|
||||
);
|
||||
PREBINDING = NO;
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "86D3FD5B-5B72-4D87-88B3-0737B204F98E";
|
||||
SDKROOT = iphonesimulator3.0;
|
||||
SDKROOT = iphoneos3.0;
|
||||
USER_HEADER_SEARCH_PATHS = "";
|
||||
};
|
||||
name = Debug;
|
||||
@ -304,8 +308,9 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Milanka Ringwald (Y4MWH89GZ9)";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Don't Code Sign";
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_VERSION = 4.2;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@ -319,8 +324,7 @@
|
||||
"-lbtstack",
|
||||
);
|
||||
PREBINDING = NO;
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "86D3FD5B-5B72-4D87-88B3-0737B204F98E";
|
||||
SDKROOT = iphonesimulator3.0;
|
||||
SDKROOT = iphoneos3.0;
|
||||
USER_HEADER_SEARCH_PATHS = "";
|
||||
};
|
||||
name = Release;
|
||||
|
@ -1,4 +1,5 @@
|
||||
Package: ch.ringwald.wiimoteopengldemo
|
||||
Package: ch.ringwald.wiimoteopengldemo
|
||||
Version: 1.0
|
||||
Name: WiiMote OpenGL-ES Demo
|
||||
Description: BTstack Demo
|
||||
This demo shows how a virtual WiiMote can mirror
|
||||
@ -10,4 +11,3 @@ Homepage: http://code.google.com/p/btstack/
|
||||
Depends: ch.ringwald.btstack
|
||||
Maintainer: Matthias Ringwald <iphone@ringwald.ch>
|
||||
Author: Matthias Ringwald <iphone@ringwald.ch>
|
||||
Version: 1.0
|
@ -120,7 +120,6 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
// bt stack activated, get started - set local name
|
||||
if (packet[2] == HCI_STATE_WORKING) {
|
||||
bt_send_cmd(&hci_write_inquiry_mode, 0x01); // with RSSI
|
||||
next();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -49,6 +49,83 @@ hci_con_handle_t con_handle;
|
||||
uint16_t hid_control = 0;
|
||||
uint16_t hid_interrupt = 0;
|
||||
|
||||
uint8_t sdp_response_0100[] = {
|
||||
0x07, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x76, 0x36, 0x01, 0xD7,
|
||||
0x36, 0x01, 0x7F, 0x09, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00,
|
||||
0x00, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19, 0x11, 0x24, 0x09,
|
||||
0x00, 0x04, 0x35, 0x0D, 0x35, 0x06, 0x19, 0x01, 0x00, 0x09,
|
||||
0x00, 0x11, 0x35, 0x03, 0x19, 0x00, 0x11, 0x09, 0x00, 0x05,
|
||||
0x35, 0x03, 0x19, 0x10, 0x02, 0x09, 0x00, 0x06, 0x35, 0x09,
|
||||
0x09, 0x65, 0x6E, 0x09, 0x00, 0x6A, 0x09, 0x01, 0x00, 0x09,
|
||||
0x00, 0x09, 0x35, 0x08, 0x35, 0x06, 0x19, 0x11, 0x24, 0x09,
|
||||
0x01, 0x00, 0x09, 0x00, 0x0D, 0x35, 0x0F, 0x35, 0x0D, 0x35,
|
||||
0x06, 0x19, 0x01, 0x00, 0x09, 0x00, 0x13, 0x35, 0x03, 0x19,
|
||||
0x00, 0x11, 0x09, 0x01, 0x00, 0x25, 0x20, 0x42, 0x72, 0x6F,
|
||||
0x61, 0x64, 0x63, 0x6F, 0x6D, 0x20, 0x42, 0x6C, 0x75, 0x65,
|
||||
0x74, 0x6F, 0x6F, 0x74, 0x68, 0x02, 0x00, 0x76
|
||||
};
|
||||
uint8_t sdp_response_0100_0076[] = {
|
||||
0x07, 0x00, 0x01, 0x00, 0x7B, 0x00, 0x76, 0x20, 0x44, 0x65,
|
||||
0x6D, 0x6F, 0x20, 0x4B, 0x65, 0x79, 0x62, 0x6F, 0x61, 0x72,
|
||||
0x64, 0x09, 0x01, 0x01, 0x25, 0x08, 0x4B, 0x65, 0x79, 0x62,
|
||||
0x6F, 0x61, 0x72, 0x64, 0x09, 0x01, 0x02, 0x25, 0x0E, 0x42,
|
||||
0x72, 0x6F, 0x61, 0x64, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F,
|
||||
0x72, 0x70, 0x2E, 0x09, 0x02, 0x00, 0x09, 0x01, 0x00, 0x09,
|
||||
0x02, 0x01, 0x09, 0x01, 0x11, 0x09, 0x02, 0x02, 0x08, 0x40,
|
||||
0x09, 0x02, 0x03, 0x08, 0x33, 0x09, 0x02, 0x04, 0x28, 0x01,
|
||||
0x09, 0x02, 0x05, 0x28, 0x01, 0x09, 0x02, 0x06, 0x35, 0x9F,
|
||||
0x35, 0x9D, 0x08, 0x22, 0x25, 0x99, 0x05, 0x01, 0x09, 0x06,
|
||||
0xA1, 0x01, 0x85, 0x01, 0x05, 0x07, 0x19, 0xE0, 0x29, 0xE7,
|
||||
0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02,
|
||||
0x95, 0x01, 0x75, 0x08, 0x81, 0x02, 0x00, 0xEC
|
||||
};
|
||||
uint8_t sdp_response_0100_00EC[] = {
|
||||
0x07, 0x00, 0x02, 0x00, 0x7B, 0x00, 0x76, 0x01, 0x95, 0x05,
|
||||
0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02,
|
||||
0x95, 0x01, 0x75, 0x03, 0x91, 0x01, 0x95, 0x06, 0x75, 0x08,
|
||||
0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65,
|
||||
0x81, 0x00, 0xC0, 0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85,
|
||||
0x02, 0x19, 0x00, 0x29, 0xFF, 0x15, 0x00, 0x25, 0xFF, 0x75,
|
||||
0x08, 0x95, 0x01, 0x81, 0x00, 0xC0, 0x05, 0x0C, 0x09, 0x01,
|
||||
0xA1, 0x01, 0x85, 0x05, 0x05, 0x01, 0x09, 0x06, 0xA1, 0x02,
|
||||
0x05, 0x06, 0x09, 0x20, 0x15, 0x00, 0x25, 0xFF, 0x75, 0x08,
|
||||
0x95, 0x08, 0x81, 0x00, 0x09, 0x20, 0x15, 0x00, 0x25, 0xFF,
|
||||
0x75, 0x08, 0x95, 0x08, 0xB1, 0x00, 0xC0, 0x05, 0x0C, 0x09,
|
||||
0x01, 0xA1, 0x01, 0x85, 0x06, 0x19, 0x00, 0x29, 0xFE, 0x15,
|
||||
0x00, 0x25, 0xFF, 0x75, 0x08, 0x02, 0x01, 0x62
|
||||
};
|
||||
uint8_t sdp_response_0100_0162[] = {
|
||||
0x07, 0x00, 0x03, 0x00, 0x7B, 0x00, 0x76, 0x95, 0x02, 0x81,
|
||||
0x00, 0xC0, 0xC0, 0x09, 0x02, 0x07, 0x35, 0x08, 0x35, 0x06,
|
||||
0x09, 0x03, 0x09, 0x09, 0x01, 0x00, 0x09, 0x02, 0x0B, 0x09,
|
||||
0x01, 0x00, 0x09, 0x02, 0x0D, 0x28, 0x00, 0x09, 0x02, 0x0E,
|
||||
0x28, 0x01, 0x36, 0x00, 0x52, 0x09, 0x00, 0x00, 0x0A, 0x00,
|
||||
0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19, 0x12,
|
||||
0x00, 0x09, 0x00, 0x04, 0x35, 0x0D, 0x35, 0x06, 0x19, 0x01,
|
||||
0x00, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19, 0x00, 0x01, 0x09,
|
||||
0x00, 0x09, 0x35, 0x08, 0x35, 0x06, 0x19, 0x12, 0x00, 0x09,
|
||||
0x01, 0x00, 0x09, 0x02, 0x00, 0x09, 0x01, 0x00, 0x09, 0x02,
|
||||
0x01, 0x09, 0x0A, 0x5C, 0x09, 0x02, 0x02, 0x09, 0x20, 0x01,
|
||||
0x09, 0x02, 0x03, 0x09, 0x01, 0x07, 0x09, 0x02, 0x04, 0x28,
|
||||
0x01, 0x09, 0x02, 0x05, 0x09, 0x02, 0x01, 0xD8
|
||||
};
|
||||
uint8_t sdp_response_0100_01D8[] = {
|
||||
0x07, 0x00, 0x04, 0x00, 0x05, 0x00, 0x02, 0x00, 0x02, 0x00
|
||||
};
|
||||
|
||||
uint8_t sdp_response_1200[] = {
|
||||
0x07, 0x00, 0x01, 0x00, 0x5B, 0x00, 0x58, 0x36, 0x00, 0x55,
|
||||
0x36, 0x00, 0x52, 0x09, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00,
|
||||
0x01, 0x09, 0x00, 0x01, 0x35, 0x03, 0x19, 0x12, 0x00, 0x09,
|
||||
0x00, 0x04, 0x35, 0x0D, 0x35, 0x06, 0x19, 0x01, 0x00, 0x09,
|
||||
0x00, 0x01, 0x35, 0x03, 0x19, 0x00, 0x01, 0x09, 0x00, 0x09,
|
||||
0x35, 0x08, 0x35, 0x06, 0x19, 0x12, 0x00, 0x09, 0x01, 0x00,
|
||||
0x09, 0x02, 0x00, 0x09, 0x01, 0x00, 0x09, 0x02, 0x01, 0x09,
|
||||
0x0A, 0x5C, 0x09, 0x02, 0x02, 0x09, 0x20, 0x01, 0x09, 0x02,
|
||||
0x03, 0x09, 0x01, 0x07, 0x09, 0x02, 0x04, 0x28, 0x01, 0x09,
|
||||
0x02, 0x05, 0x09, 0x00, 0x02, 0x00
|
||||
};
|
||||
|
||||
void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
|
||||
bd_addr_t event_addr;
|
||||
@ -58,13 +135,53 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
uint16_t remote_cid;
|
||||
char pin[20];
|
||||
int i;
|
||||
|
||||
uint16_t UUID;
|
||||
uint16_t cont = 0;
|
||||
uint8_t * response;
|
||||
uint16_t len;
|
||||
switch (packet_type) {
|
||||
|
||||
case L2CAP_DATA_PACKET:
|
||||
// just dump data for now
|
||||
printf("source cid %x -- ", channel);
|
||||
hexdump( packet, size );
|
||||
//
|
||||
if (packet[0] != 0x06) return; // no sdp request
|
||||
UUID = packet[8] << 8 | packet [9];
|
||||
switch (UUID) {
|
||||
case 0x0100:
|
||||
if (packet[19]){
|
||||
cont = packet[20] << 8 | packet [21];
|
||||
}
|
||||
switch (cont) {
|
||||
case 0:
|
||||
response = sdp_response_0100;
|
||||
len = sizeof(sdp_response_0100);
|
||||
break;
|
||||
case 0x0076:
|
||||
response = sdp_response_0100_0076;
|
||||
len = sizeof(sdp_response_0100_0076);
|
||||
break;
|
||||
case 0x00EC:
|
||||
response = sdp_response_0100_00EC;
|
||||
len = sizeof(sdp_response_0100_00EC);
|
||||
break;
|
||||
case 0x0162:
|
||||
response = sdp_response_0100_0162;
|
||||
len = sizeof(sdp_response_0100_0162);
|
||||
break;
|
||||
case 0x01d8:
|
||||
response = sdp_response_0100_01D8;
|
||||
len = sizeof(sdp_response_0100_01D8);
|
||||
break;
|
||||
}
|
||||
memcpy(response+1, &packet[1], 2);
|
||||
bt_send_l2cap( channel, response, len);
|
||||
printf("answering 0100 request, cont %u\n", cont);
|
||||
break;
|
||||
case 0x1200:
|
||||
memcpy(sdp_response_1200+1, &packet[1], 2);
|
||||
bt_send_l2cap( channel, sdp_response_1200, sizeof(sdp_response_1200));
|
||||
printf("answering 1200 request\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
@ -106,7 +223,7 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
break;
|
||||
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
// inform about pin code request
|
||||
/* // inform about pin code request
|
||||
printf("Please enter PIN here: ");
|
||||
fgets(pin, 20, stdin);
|
||||
i = strlen(pin)-1;
|
||||
@ -114,6 +231,8 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
pin[i] = '\0';
|
||||
}
|
||||
printf("PIN = '%s'\n", pin);
|
||||
*/
|
||||
strcpy(pin, "0000");
|
||||
bt_flip_addr(event_addr, &packet[2]);
|
||||
bt_send_cmd(&hci_pin_code_request_reply, &event_addr, strlen(pin), pin);
|
||||
break;
|
||||
@ -129,16 +248,6 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
print_bd_addr(event_addr);
|
||||
printf(", handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
|
||||
handle, psm, local_cid, READ_BT_16(packet, 15));
|
||||
|
||||
if (psm == PSM_HID_CONTROL){
|
||||
hid_control = local_cid;
|
||||
}
|
||||
if (psm == PSM_HID_INTERRUPT){
|
||||
hid_interrupt = local_cid;
|
||||
}
|
||||
if (hid_control && hid_interrupt){
|
||||
bt_send_cmd(&hci_switch_role_command, &event_addr, 0);
|
||||
}
|
||||
} else {
|
||||
printf("L2CAP connection to device ");
|
||||
print_bd_addr(event_addr);
|
||||
@ -146,14 +255,7 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_ROLE_CHANGE: {
|
||||
//HID Control: 0x06 bytes - SET_FEATURE_REPORT [ 53 F4 42 03 00 00 ]
|
||||
uint8_t set_feature_report[] = { 0x53, 0xf4, 0x42, 0x03, 0x00, 0x00};
|
||||
bt_send_l2cap(hid_control, (uint8_t*) &set_feature_report, sizeof(set_feature_report));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
// connection closed -> quit tes app
|
||||
printf("Basebank connection closed\n");
|
||||
@ -185,6 +287,7 @@ int main (int argc, const char * argv[]){
|
||||
return err;
|
||||
}
|
||||
bt_register_packet_handler(packet_handler);
|
||||
bt_send_cmd(&l2cap_register_service, PSM_SDP, 250);
|
||||
bt_send_cmd(&l2cap_register_service, PSM_HID_CONTROL, 250);
|
||||
bt_send_cmd(&l2cap_register_service, PSM_HID_INTERRUPT, 250);
|
||||
|
||||
|
494
example/rfcomm.c
494
example/rfcomm.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
* Copyright (C) 2010 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* test.c
|
||||
* rfcomm.c
|
||||
*
|
||||
* Command line parsing and debug option
|
||||
* added by Vladimir Vyskocil <vladimir.vyskocil@gmail.com>
|
||||
@ -48,264 +48,32 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <btstack/btstack.h>
|
||||
#include <btstack/sdp_util.h>
|
||||
|
||||
// copy and paste from BTnut
|
||||
|
||||
// Control field values bit no. 1 2 3 4 5 6 7 8
|
||||
#define BT_RFCOMM_SABM 0x3F // 1 1 1 1 P/F 1 0 0
|
||||
#define BT_RFCOMM_UA 0x73 // 1 1 0 0 P/F 1 1 0
|
||||
#define BT_RFCOMM_DM 0x0F // 1 1 1 1 P/F 0 0 0
|
||||
#define BT_RFCOMM_DM_PF 0x1F
|
||||
#define BT_RFCOMM_DISC 0x53 // 1 1 0 0 P/F 0 1 1
|
||||
#define BT_RFCOMM_UIH 0xEF // 1 1 1 1 P/F 1 1 1
|
||||
#define BT_RFCOMM_UIH_PF 0xFF
|
||||
|
||||
// Multiplexer message types
|
||||
#define BT_RFCOMM_PN_CMD 0x83
|
||||
#define BT_RFCOMM_PN_RSP 0x81
|
||||
#define BT_RFCOMM_TEST_CMD 0x23
|
||||
#define BT_RFCOMM_TEST_RSP 0x21
|
||||
#define BT_RFCOMM_FCON_CMD 0xA3
|
||||
#define BT_RFCOMM_FCON_RSP 0xA1
|
||||
#define BT_RFCOMM_FCOFF_CMD 0x63
|
||||
#define BT_RFCOMM_FCOFF_RSP 0x61
|
||||
#define BT_RFCOMM_MSC_CMD 0xE3
|
||||
#define BT_RFCOMM_MSC_RSP 0xE1
|
||||
#define BT_RFCOMM_RPN_CMD 0x93
|
||||
#define BT_RFCOMM_RPN_RSP 0x91
|
||||
#define BT_RFCOMM_RLS_CMD 0x53
|
||||
#define BT_RFCOMM_RLS_RSP 0x51
|
||||
#define BT_RFCOMM_NSC_RSP 0x11
|
||||
|
||||
// FCS calc
|
||||
#define BT_RFCOMM_CODE_WORD 0xE0 // pol = x8+x2+x1+1
|
||||
#define BT_RFCOMM_CRC_CHECK_LEN 3
|
||||
#define BT_RFCOMM_UIHCRC_CHECK_LEN 2
|
||||
|
||||
#define NR_CREDITS 0x30
|
||||
|
||||
bd_addr_t addr = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
int RFCOMM_CHANNEL_ID = 1;
|
||||
char PIN[] = "0000";
|
||||
|
||||
int DEBUG = 0;
|
||||
|
||||
hci_con_handle_t con_handle;
|
||||
uint16_t source_cid;
|
||||
int fifo_fd;
|
||||
|
||||
// used to assemble rfcomm packets
|
||||
uint8_t rfcomm_out_buffer[1000];
|
||||
|
||||
/**
|
||||
* @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1
|
||||
*/
|
||||
void rfcomm_send_packet(uint16_t source_cid, uint8_t address, uint8_t control, uint8_t credits, uint8_t *data, uint16_t len){
|
||||
|
||||
uint16_t pos = 0;
|
||||
uint8_t crc_fields = 3;
|
||||
|
||||
rfcomm_out_buffer[pos++] = address;
|
||||
rfcomm_out_buffer[pos++] = control;
|
||||
|
||||
// length field can be 1 or 2 octets
|
||||
if (len < 128){
|
||||
rfcomm_out_buffer[pos++] = (len << 1)| 1; // bits 0-6
|
||||
} else {
|
||||
rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
|
||||
rfcomm_out_buffer[pos++] = len >> 7; // bits 7-14
|
||||
crc_fields++;
|
||||
}
|
||||
|
||||
// add credits for UIH frames when PF bit is set
|
||||
if (control == BT_RFCOMM_UIH_PF){
|
||||
rfcomm_out_buffer[pos++] = credits;
|
||||
}
|
||||
|
||||
// copy actual data
|
||||
memcpy(&rfcomm_out_buffer[pos], data, len);
|
||||
pos += len;
|
||||
|
||||
// UIH frames only calc FCS over address + control (5.1.1)
|
||||
if ((control & 0xef) == BT_RFCOMM_UIH){
|
||||
crc_fields = 2;
|
||||
}
|
||||
rfcomm_out_buffer[pos++] = crc8_calc(rfcomm_out_buffer, crc_fields); // calc fcs
|
||||
bt_send_l2cap( source_cid, rfcomm_out_buffer, pos);
|
||||
}
|
||||
|
||||
void _bt_rfcomm_send_sabm(uint16_t source_cid, uint8_t initiator, uint8_t channel)
|
||||
{
|
||||
uint8_t address = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
|
||||
rfcomm_send_packet(source_cid, address, BT_RFCOMM_SABM, 0, NULL, 0);
|
||||
}
|
||||
|
||||
void _bt_rfcomm_send_uih_data(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t *data, uint16_t len) {
|
||||
uint8_t address = (1 << 0) | (initiator << 1) | (initiator << 1) | (channel << 3);
|
||||
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, data, len);
|
||||
}
|
||||
|
||||
void _bt_rfcomm_send_uih_msc_cmd(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t signals)
|
||||
{
|
||||
uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
|
||||
uint8_t payload[4];
|
||||
uint8_t pos = 0;
|
||||
payload[pos++] = BT_RFCOMM_MSC_CMD;
|
||||
payload[pos++] = 2 << 1 | 1; // len
|
||||
payload[pos++] = (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3); // shouldn't D = initiator = 1 ?
|
||||
payload[pos++] = signals;
|
||||
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
||||
}
|
||||
|
||||
void _bt_rfcomm_send_uih_pn_command(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint16_t max_frame_size){
|
||||
uint8_t payload[10];
|
||||
uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
|
||||
uint8_t pos = 0;
|
||||
payload[pos++] = BT_RFCOMM_PN_CMD;
|
||||
payload[pos++] = 8 << 1 | 1; // len
|
||||
payload[pos++] = channel << 1;
|
||||
payload[pos++] = 0xf0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
|
||||
payload[pos++] = 0; // priority
|
||||
payload[pos++] = 0; // max 60 seconds ack
|
||||
payload[pos++] = max_frame_size & 0xff; // max framesize low
|
||||
payload[pos++] = max_frame_size >> 8; // max framesize high
|
||||
payload[pos++] = 0x00; // number of retransmissions
|
||||
payload[pos++] = 0x00; // unused error recovery window
|
||||
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
|
||||
}
|
||||
// input from command line arguments
|
||||
bd_addr_t addr = { };
|
||||
uint16_t con_handle;
|
||||
int rfcomm_channel = 1;
|
||||
char pin[17];
|
||||
|
||||
void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
bd_addr_t event_addr;
|
||||
|
||||
static uint8_t msc_resp_send = 0;
|
||||
static uint8_t msc_resp_received = 0;
|
||||
static uint8_t credits_used = 0;
|
||||
static uint8_t credits_free = 0;
|
||||
uint8_t packet_processed = 0;
|
||||
uint16_t mtu;
|
||||
uint16_t psm;
|
||||
uint16_t rfcomm_channel_id;
|
||||
uint16_t rfcomm_channel_nr;
|
||||
uint8_t credits;
|
||||
static uint32_t packet_counter = 0;
|
||||
static char packet_info[30]; // "packets: 1234567890"
|
||||
|
||||
switch (packet_type) {
|
||||
|
||||
case L2CAP_DATA_PACKET:
|
||||
// rfcomm: data[8] = addr
|
||||
// rfcomm: data[9] = command
|
||||
|
||||
// received 1. message BT_RF_COMM_UA
|
||||
if (size == 4 && packet[1] == BT_RFCOMM_UA && packet[0] == 0x03){
|
||||
packet_processed++;
|
||||
printf("Received RFCOMM unnumbered acknowledgement for channel 0 - multiplexer working\n");
|
||||
printf("Sending UIH Parameter Negotiation Command\n");
|
||||
_bt_rfcomm_send_uih_pn_command(source_cid, 1, RFCOMM_CHANNEL_ID, 100);
|
||||
}
|
||||
|
||||
// received UIH Parameter Negotiation Response
|
||||
if (size == 14 && packet[1] == BT_RFCOMM_UIH && packet[3] == BT_RFCOMM_PN_RSP){
|
||||
packet_processed++;
|
||||
printf("UIH Parameter Negotiation Response\n");
|
||||
printf("Sending SABM #%u\n", RFCOMM_CHANNEL_ID);
|
||||
_bt_rfcomm_send_sabm(source_cid, 1, RFCOMM_CHANNEL_ID);
|
||||
}
|
||||
|
||||
// received 2. message BT_RF_COMM_UA
|
||||
if (size == 4 && packet[1] == BT_RFCOMM_UA && packet[0] == ((RFCOMM_CHANNEL_ID << 3) | 3) ){
|
||||
packet_processed++;
|
||||
printf("Received RFCOMM unnumbered acknowledgement for channel %u - channel opened\n", RFCOMM_CHANNEL_ID);
|
||||
printf("Sending MSC 'I'm ready'\n");
|
||||
_bt_rfcomm_send_uih_msc_cmd(source_cid, 1, RFCOMM_CHANNEL_ID, 0x8d); // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
|
||||
}
|
||||
|
||||
// received BT_RFCOMM_MSC_CMD
|
||||
if (size == 8 && packet[1] == BT_RFCOMM_UIH && packet[3] == BT_RFCOMM_MSC_CMD){
|
||||
packet_processed++;
|
||||
printf("Received BT_RFCOMM_MSC_CMD\n");
|
||||
printf("Responding to 'I'm ready'\n");
|
||||
// fine with this
|
||||
uint8_t address = packet[0] | 2; // set response
|
||||
packet[3] = BT_RFCOMM_MSC_RSP; // " "
|
||||
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0x30, (uint8_t*)&packet[3], 4);
|
||||
msc_resp_send = 1;
|
||||
}
|
||||
|
||||
// received BT_RFCOMM_MSC_RSP
|
||||
if (size == 8 && packet[1] == BT_RFCOMM_UIH && packet[3] == BT_RFCOMM_MSC_RSP){
|
||||
packet_processed++;
|
||||
msc_resp_received = 1;
|
||||
}
|
||||
|
||||
if (packet[1] == BT_RFCOMM_UIH && packet[0] == ((RFCOMM_CHANNEL_ID<<3)|1)){
|
||||
packet_processed++;
|
||||
credits_used++;
|
||||
if(DEBUG){
|
||||
printf("RX: address %02x, control %02x: ", packet[0], packet[1]);
|
||||
hexdump( (uint8_t*) &packet[3], size-4);
|
||||
}
|
||||
int written = 0;
|
||||
int length = size-4;
|
||||
int start_of_data = 3;
|
||||
//write data to fifo
|
||||
while (length) {
|
||||
if ((written = write(fifo_fd, &packet[start_of_data], length)) == -1) {
|
||||
printf("Error writing to FIFO\n");
|
||||
} else {
|
||||
length -= written;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (packet[1] == BT_RFCOMM_UIH_PF && packet[0] == ((RFCOMM_CHANNEL_ID<<3)|1)){
|
||||
packet_processed++;
|
||||
credits_used++;
|
||||
if (!credits_free) {
|
||||
printf("Got %u credits, can send!\n", packet[2]);
|
||||
}
|
||||
credits_free = packet[2];
|
||||
if(DEBUG){
|
||||
printf("RX: address %02x, control %02x: ", packet[0], packet[1]);
|
||||
hexdump( (uint8_t *) &packet[4], size-5);
|
||||
}
|
||||
int written = 0;
|
||||
int length = size-5;
|
||||
int start_of_data = 4;
|
||||
//write data to fifo
|
||||
while (length) {
|
||||
if ((written = write(fifo_fd, &packet[start_of_data], length)) == -1) {
|
||||
printf("Error writing to FIFO\n");
|
||||
} else {
|
||||
length -= written;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t send_credits_packet = 0;
|
||||
|
||||
if (credits_used >= NR_CREDITS ) {
|
||||
send_credits_packet = 1;
|
||||
credits_used -= NR_CREDITS;
|
||||
}
|
||||
|
||||
if (msc_resp_send && msc_resp_received) {
|
||||
send_credits_packet = 1;
|
||||
msc_resp_send = msc_resp_received = 0;
|
||||
|
||||
printf("RFCOMM up and running!\n");
|
||||
}
|
||||
|
||||
if (send_credits_packet) {
|
||||
// send 0x30 credits
|
||||
uint8_t initiator = 1;
|
||||
uint8_t address = (1 << 0) | (initiator << 1) | (initiator << 1) | (RFCOMM_CHANNEL_ID << 3);
|
||||
rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH_PF, NR_CREDITS, NULL, 0);
|
||||
}
|
||||
|
||||
if (!packet_processed){
|
||||
// just dump data for now
|
||||
printf("??: address %02x, control %02x: ", packet[0], packet[1]);
|
||||
hexdump( packet, size );
|
||||
}
|
||||
|
||||
case RFCOMM_DATA_PACKET:
|
||||
printf("Received RFCOMM data on channel id %u, size %u\n", channel, size);
|
||||
hexdump(packet, size);
|
||||
break;
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
|
||||
switch (packet[0]) {
|
||||
|
||||
case BTSTACK_EVENT_POWERON_FAILED:
|
||||
@ -317,68 +85,75 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
case BTSTACK_EVENT_STATE:
|
||||
// bt stack activated, get started - use authentication yes/no
|
||||
if (packet[2] == HCI_STATE_WORKING) {
|
||||
bt_send_cmd(&hci_write_authentication_enable, 1);
|
||||
bt_send_cmd(&hci_write_class_of_device, 0x1f00);
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_LINK_KEY_REQUEST:
|
||||
// link key request
|
||||
bt_flip_addr(event_addr, &packet[2]);
|
||||
bt_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
|
||||
break;
|
||||
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
// inform about pin code request
|
||||
bt_flip_addr(event_addr, &packet[2]);
|
||||
bt_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, PIN);
|
||||
printf("Please enter PIN %s on remote device\n", PIN);
|
||||
break;
|
||||
|
||||
case L2CAP_EVENT_CHANNEL_OPENED:
|
||||
// inform about new l2cap connection
|
||||
bt_flip_addr(event_addr, &packet[3]);
|
||||
uint16_t psm = READ_BT_16(packet, 11);
|
||||
source_cid = READ_BT_16(packet, 13);
|
||||
con_handle = READ_BT_16(packet, 9);
|
||||
if (packet[2] == 0) {
|
||||
printf("Channel successfully opened: ");
|
||||
print_bd_addr(event_addr);
|
||||
printf(", handle 0x%02x, psm 0x%02x, source cid 0x%02x, dest cid 0x%02x\n",
|
||||
con_handle, psm, source_cid, READ_BT_16(packet, 15));
|
||||
|
||||
// send SABM command on dlci 0
|
||||
printf("Sending SABM #0\n");
|
||||
_bt_rfcomm_send_sabm(source_cid, 1, 0);
|
||||
} else {
|
||||
printf("L2CAP connection to device ");
|
||||
print_bd_addr(event_addr);
|
||||
printf(" failed. status code %u\n", packet[2]);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
// connection closed -> quit test app
|
||||
printf("Basebank connection closed, exit.\n");
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
// connect to RFCOMM device (PSM 0x03) at addr
|
||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
|
||||
bt_send_cmd(&l2cap_create_channel, addr, 0x03);
|
||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_class_of_device) ) {
|
||||
// outgoing only:
|
||||
bt_send_cmd(&rfcomm_create_channel, addr, rfcomm_channel);
|
||||
}
|
||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr) ) {
|
||||
bt_flip_addr(event_addr, &packet[6]);
|
||||
printf("Own BD_ADDR: ");
|
||||
print_bd_addr(event_addr);
|
||||
printf("\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
// inform about pin code request
|
||||
printf("Using PIN 0000\n");
|
||||
bt_flip_addr(event_addr, &packet[2]);
|
||||
bt_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
|
||||
break;
|
||||
|
||||
case RFCOMM_EVENT_INCOMING_CONNECTION:
|
||||
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
|
||||
bt_flip_addr(event_addr, &packet[2]);
|
||||
rfcomm_channel_nr = packet[8];
|
||||
rfcomm_channel_id = READ_BT_16(packet, 9);
|
||||
printf("RFCOMM channel %u requested for ", rfcomm_channel_nr);
|
||||
print_bd_addr(event_addr);
|
||||
printf("\n");
|
||||
bt_send_cmd(&rfcomm_accept_connection, rfcomm_channel_id);
|
||||
break;
|
||||
|
||||
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
|
||||
// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
|
||||
if (packet[2]) {
|
||||
printf("RFCOMM channel open failed, status %u\n", packet[2]);
|
||||
} else {
|
||||
rfcomm_channel_id = READ_BT_16(packet, 10);
|
||||
mtu = READ_BT_16(packet, 12);
|
||||
printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_channel_id, mtu);
|
||||
uint8_t message[] = "Hello World from BTstack!\n";
|
||||
// bt_send_rfcomm(rfcomm_channel_id, message, sizeof(message));
|
||||
}
|
||||
break;
|
||||
|
||||
case RFCOMM_EVENT_CREDITS:
|
||||
// how many? for whom?
|
||||
rfcomm_channel_id = READ_BT_16(packet, 2);
|
||||
credits = packet[4];
|
||||
//
|
||||
packet_counter++;
|
||||
sprintf(packet_info, "\rPacket counter: %09u", packet_counter);
|
||||
bt_send_rfcomm(rfcomm_channel_id, packet_info, strlen(packet_info));
|
||||
break;
|
||||
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
// connection closed -> quit test app
|
||||
printf("Basebank connection closed\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
// unhandled event
|
||||
if(DEBUG) printf("unhandled event : %02x\n", packet[0]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// unhandled packet type
|
||||
if(DEBUG) printf("unhandled packet type : %02x\n", packet_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -387,9 +162,79 @@ void usage(const char *name){
|
||||
fprintf(stderr, "Usage : %s [-a|--address aa:bb:cc:dd:ee:ff] [-c|--channel n] [-p|--pin nnnn]\n", name);
|
||||
}
|
||||
|
||||
#define FIFO_NAME "/tmp/rfcomm0"
|
||||
uint8_t service_buffer[100];
|
||||
|
||||
void create_spp_service(uint8_t *service){
|
||||
|
||||
uint8_t* attribute;
|
||||
de_create_sequence(service);
|
||||
|
||||
// 0x0001 "Service Class ID List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0001);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1101 );
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0004 "Protocol Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0004);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t* l2cpProtocol = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, 0x0100);
|
||||
}
|
||||
de_pop_sequence(attribute, l2cpProtocol);
|
||||
|
||||
uint8_t* rfcomm = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(rfcomm, DE_UUID, DE_SIZE_16, 0x0003); // rfcomm_service
|
||||
de_add_number(rfcomm, DE_UINT, DE_SIZE_8, 0x0001); // rfcomm channel
|
||||
}
|
||||
de_pop_sequence(attribute, rfcomm);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0005 "Public Browse Group"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0005); // public browse group
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1002 );
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0006
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, SDP_LanguageBaseAttributeIDList);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e);
|
||||
de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a);
|
||||
de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0009 "Bluetooth Profile Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0009);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t *sppProfile = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(sppProfile, DE_UUID, DE_SIZE_16, 0x1101);
|
||||
de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0100);
|
||||
}
|
||||
de_pop_sequence(attribute, sppProfile);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0100 "ServiceName"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100);
|
||||
de_add_data(service, DE_STRING, 3, (uint8_t *) "CMD");
|
||||
}
|
||||
|
||||
int main (int argc, const char * argv[]){
|
||||
|
||||
#if 1
|
||||
int arg = 1;
|
||||
|
||||
if (argc == 1){
|
||||
@ -405,45 +250,50 @@ int main (int argc, const char * argv[]){
|
||||
}
|
||||
} else if (!strcmp(argv[arg], "-c") || !strcmp(argv[arg], "--channel")) {
|
||||
arg++;
|
||||
if(arg >= argc || !sscanf(argv[arg], "%d", &RFCOMM_CHANNEL_ID)){
|
||||
if(arg >= argc || !sscanf(argv[arg], "%d", &rfcomm_channel)){
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
} else if (!strcmp(argv[arg], "-p") || !strcmp(argv[arg], "--pin")) {
|
||||
arg++;
|
||||
int pin1,pin2,pin3,pin4;
|
||||
if(arg >= argc || sscanf(argv[arg], "%1d%1d%1d%1d", &pin1, &pin2, &pin3, &pin4) != 4){
|
||||
if(arg >= argc) {
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
snprintf(PIN, 5, "%01d%01d%01d%01d", pin1, pin2, pin3, pin4);
|
||||
strncpy(pin, argv[arg], 16);
|
||||
pin[16] = 0;
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
printf("Waiting for client to open %s...\n", FIFO_NAME);
|
||||
int err = mknod(FIFO_NAME, S_IFIFO | 0666, 0);
|
||||
if(err >= 0 || errno == EEXIST){
|
||||
fifo_fd = open(FIFO_NAME, O_WRONLY);
|
||||
run_loop_init(RUN_LOOP_POSIX);
|
||||
err = bt_open();
|
||||
if (err) {
|
||||
fprintf(stderr,"Failed to open connection to BTdaemon, err %d\n",err);
|
||||
return 1;
|
||||
}
|
||||
printf("Trying connection to ");
|
||||
print_bd_addr(addr);
|
||||
printf(" channel %d\n", RFCOMM_CHANNEL_ID);
|
||||
bt_register_packet_handler(packet_handler);
|
||||
bt_send_cmd(&btstack_set_power_mode, HCI_POWER_ON );
|
||||
run_loop_execute();
|
||||
bt_close();
|
||||
} else {
|
||||
fprintf(stderr, "Failed mknod %s, errno %d\n", FIFO_NAME, errno);
|
||||
#endif
|
||||
|
||||
run_loop_init(RUN_LOOP_POSIX);
|
||||
int err = bt_open();
|
||||
if (err) {
|
||||
fprintf(stderr,"Failed to open connection to BTdaemon, err %d\n",err);
|
||||
return 1;
|
||||
}
|
||||
bt_register_packet_handler(packet_handler);
|
||||
|
||||
#if 1
|
||||
printf("Trying connection to ");
|
||||
print_bd_addr(addr);
|
||||
printf(" channel %d\n", rfcomm_channel);
|
||||
#endif
|
||||
|
||||
// register RFCOM channel
|
||||
bt_send_cmd(&rfcomm_register_service, 1, 100);
|
||||
|
||||
// register SDP for our SPP
|
||||
create_spp_service(service_buffer);
|
||||
bt_send_cmd(&sdp_register_service_record, service_buffer);
|
||||
|
||||
bt_send_cmd(&btstack_set_power_mode, HCI_POWER_ON );
|
||||
run_loop_execute();
|
||||
bt_close();
|
||||
return 0;
|
||||
}
|
||||
|
@ -45,7 +45,8 @@
|
||||
|
||||
// bd_addr_t addr = {0x00, 0x03, 0xc9, 0x3d, 0x77, 0x43 }; // Think Outside Keyboard
|
||||
// bd_addr_t addr = {0x00, 0x19, 0x1d, 0x90, 0x44, 0x68 }; // WiiMote
|
||||
bd_addr_t addr = {0x76, 0x6d, 0x62, 0xdb, 0xca, 0x73 }; // iPad
|
||||
// bd_addr_t addr = {0x76, 0x6d, 0x62, 0xdb, 0xca, 0x73 }; // iPad
|
||||
bd_addr_t addr = {0x00, 0x06, 0x66, 0x42, 0x16, 0xf5 }; // iControlPad-16f5
|
||||
|
||||
hci_con_handle_t con_handle;
|
||||
uint16_t source_cid_interrupt;
|
||||
@ -61,16 +62,6 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
// just dump data for now
|
||||
printf("source cid %x -- ", channel);
|
||||
hexdump( packet, size );
|
||||
|
||||
// HOME => disconnect
|
||||
if (packet[0] == 0xA1) { // Status report
|
||||
if (packet[1] == 0x30 || packet[1] == 0x31) { // type 0x30 or 0x31
|
||||
if (packet[3] & 0x080) { // homne button pressed
|
||||
printf("Disconnect baseband\n");
|
||||
bt_send_cmd(&hci_disconnect, con_handle, 0x13); // remote closed connection
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
@ -85,7 +76,7 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
case BTSTACK_EVENT_STATE:
|
||||
// bt stack activated, get started - disable pairing
|
||||
if (packet[2] == HCI_STATE_WORKING) {
|
||||
bt_send_cmd(&hci_write_authentication_enable, 0);
|
||||
bt_send_cmd(&hci_write_authentication_enable, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -100,7 +91,7 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
// inform about pin code request
|
||||
printf("Please enter PIN 0000 on remote device\n");
|
||||
bt_flip_addr(event_addr, &packet[2]);
|
||||
bt_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
|
||||
bt_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "1234");
|
||||
break;
|
||||
|
||||
case L2CAP_EVENT_CHANNEL_OPENED:
|
||||
@ -118,8 +109,6 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
|
||||
if (psm == 0x13) {
|
||||
source_cid_interrupt = source_cid;
|
||||
// interupt channel openedn succesfully, now open control channel, too.
|
||||
bt_send_cmd(&l2cap_create_channel, event_addr, 0x11);
|
||||
} else {
|
||||
source_cid_control = source_cid;
|
||||
// request acceleration data..
|
||||
@ -128,6 +117,7 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
// stop blinking
|
||||
// uint8_t setLEDs[] = { 0x52, 0x11, 0x10 };
|
||||
// bt_send_l2cap( source_cid, setLEDs, sizeof(setLEDs));
|
||||
bt_send_cmd(&l2cap_create_channel, event_addr, 0x13);
|
||||
}
|
||||
} else {
|
||||
printf("L2CAP connection to device ");
|
||||
@ -146,7 +136,7 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
// connect to HID device (PSM 0x13) at addr
|
||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
|
||||
bt_send_cmd(&l2cap_create_channel, addr, 0x13);
|
||||
bt_send_cmd(&l2cap_create_channel, addr, 0x11);
|
||||
printf("Press 1+2 on WiiMote to make it discoverable - Press HOME to disconnect later :)\n");
|
||||
}
|
||||
break;
|
||||
|
@ -79,6 +79,7 @@ btstack_packet_handler_t bt_register_packet_handler(btstack_packet_handler_t han
|
||||
void bt_send_acl(uint8_t * data, uint16_t len);
|
||||
|
||||
void bt_send_l2cap(uint16_t local_cid, uint8_t *data, uint16_t len);
|
||||
void bt_send_rfcomm(uint16_t rfcom_cid, uint8_t *data, uint16_t len);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
|
@ -143,6 +143,30 @@ extern "C" {
|
||||
// data: event(8), len(8), local_cid(16), credits(8)
|
||||
#define L2CAP_EVENT_CREDITS 0x74
|
||||
|
||||
|
||||
// RFCOMM EVENTS
|
||||
|
||||
// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
|
||||
// status: 0 = OK
|
||||
#define RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE 0x80
|
||||
|
||||
// data: event(8), len(8), channelID(8)
|
||||
// status: 0 = OK
|
||||
#define RFCOMM_EVENT_CHANNEL_CLOSED 0x81
|
||||
|
||||
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
|
||||
#define RFCOMM_EVENT_INCOMING_CONNECTION 0x82
|
||||
|
||||
// data: event (8), len(8), rfcommid (16), ...
|
||||
#define RFCOMM_EVENT_REMOTE_LINE_STATUS 0x83
|
||||
|
||||
// data: event(8), len(8), local_cid(16), credits(8)
|
||||
#define RFCOMM_EVENT_CREDITS 0x84
|
||||
|
||||
// data: event(8), len(8), status (8), registration id(16), rfcomm server channel id (8)
|
||||
#define RFCOMM_EVENT_SERVICE_REGISTERED 0x85
|
||||
|
||||
|
||||
// data: event(8), len(8), service_record_handle(32)
|
||||
#define SDP_SERVICE_REGISTERED 0x90
|
||||
|
||||
@ -173,6 +197,8 @@ extern "C" {
|
||||
#define L2CAP_CONFIG_RESPONSE_RESULT_REJECTED 0x68
|
||||
#define L2CAP_CONFIG_RESPONSE_RESULT_UNKNOWN_OPTIONS 0x69
|
||||
|
||||
#define RFCOMM_MULTIPLEXER_STOPPED 0x70
|
||||
|
||||
/**
|
||||
* Default INQ Mode
|
||||
*/
|
||||
|
@ -4,7 +4,7 @@ PACKAGE=BTstack
|
||||
|
||||
svn update
|
||||
|
||||
VERSION=0.2
|
||||
VERSION=0.3
|
||||
REVISION=`svn info | grep Revision | cut -d " " -f 2`
|
||||
ARCHIVE=$PACKAGE-$VERSION-$REVISION.deb
|
||||
|
||||
@ -34,6 +34,10 @@ cp resources/Silver*.png $PACKAGE/System/Library/Frameworks/UIKit.framework/
|
||||
mkdir -p $PACKAGE/Library/LaunchDaemons/
|
||||
cp resources/ch.ringwald.BTstack.plist $PACKAGE/Library/LaunchDaemons/
|
||||
|
||||
# PrefsBundle
|
||||
pushd PrefsBundle ; make package ; popd
|
||||
cp -r PrefsBundle/_/* $PACKAGE
|
||||
|
||||
# prerm: called on remove and upgrade - stop daemon and get rid of BlueToolH4
|
||||
echo "#!/bin/sh" > $PACKAGE/DEBIAN/prerm
|
||||
echo "/bin/launchctl unload /Library/LaunchDaemons/ch.ringwald.BTstack.plist 2&> /dev/null" >> $PACKAGE/DEBIAN/prerm
|
||||
@ -56,7 +60,6 @@ echo "#!/bin/sh" > $PACKAGE/DEBIAN/postinst
|
||||
echo "/bin/launchctl load /Library/LaunchDaemons/ch.ringwald.BTstack.plist 2&> /dev/null" >> $PACKAGE/DEBIAN/postinst
|
||||
chmod +x $PACKAGE/DEBIAN/postinst
|
||||
|
||||
|
||||
# set ownership to root:root
|
||||
sudo chown -R 0:0 $PACKAGE
|
||||
|
||||
|
@ -17,17 +17,18 @@
|
||||
9C04B876107D2B7C002A63D0 /* run_loop_cocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CEB4DAA10753B4B00DD5720 /* run_loop_cocoa.m */; };
|
||||
9C04B87A107D2BA7002A63D0 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C04B879107D2BA7002A63D0 /* CoreFoundation.framework */; };
|
||||
9C05FC971020D3F300255261 /* socket_connection.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F7301017ACC3008DAB17 /* socket_connection.c */; };
|
||||
9C18015C108BAA7200824BE7 /* libusb-1.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C18015B108BAA7200824BE7 /* libusb-1.0.dylib */; };
|
||||
9C2169D212F9FB7000072B00 /* platform_iphone.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C2169D112F9FB7000072B00 /* platform_iphone.m */; };
|
||||
9C255D4A11E0C59900CDD689 /* run_loop_embedded.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C255D4911E0C59900CDD689 /* run_loop_embedded.c */; };
|
||||
9C3AED88122C201C008046F4 /* remote_device_db_iphone.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C3AED87122C201C008046F4 /* remote_device_db_iphone.m */; };
|
||||
9C46FC3A0FA906F700ABEF05 /* hci_transport_h4.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC360FA906F700ABEF05 /* hci_transport_h4.c */; };
|
||||
9C77E79210667F0600F39DCF /* platform_iphone.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C77E79110667F0600F39DCF /* platform_iphone.c */; };
|
||||
9C5E0F0E12DE39250013EF2C /* hci_transport_usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C2071F210014D3200A07EA4 /* hci_transport_usb.c */; };
|
||||
9C7B5AC0100BD3340065D87E /* linked_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7B5ABF100BD3340065D87E /* linked_list.c */; };
|
||||
9C7B5D01100FC9AE0065D87E /* btstack.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC813A10FFC0774002816F9 /* btstack.c */; };
|
||||
9C7B5D03100FC9BB0065D87E /* test.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7B5B7E100D04450065D87E /* test.c */; };
|
||||
9C7B5D0D100FC9CE0065D87E /* linked_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7B5ABF100BD3340065D87E /* linked_list.c */; };
|
||||
9C7ECBB50FCC95DD0085DAC5 /* hci_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECBB40FCC95DD0085DAC5 /* hci_dump.c */; };
|
||||
9C88500E0FBF6702004980E4 /* l2cap.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C88500C0FBF6702004980E4 /* l2cap.c */; };
|
||||
9C9F1A3D122F02DD004E21AC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C9F1A3C122F02DD004E21AC /* Foundation.framework */; };
|
||||
9CB9846B11BC32A800A2F346 /* sdp_util.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CB9846A11BC32A800A2F346 /* sdp_util.c */; };
|
||||
9CC813A50FFC0A51002816F9 /* daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC813A40FFC0A51002816F9 /* daemon.c */; };
|
||||
9CCE6CEA1025BD0000FCE9F4 /* hci.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC340FA906F700ABEF05 /* hci.c */; };
|
||||
@ -68,9 +69,9 @@
|
||||
9C13C9FC10ECED6300B04243 /* BTDevice.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; name = BTDevice.m; path = CocoaTouch/src/BTDevice.m; sourceTree = "<group>"; };
|
||||
9C13C9FD10ECED6300B04243 /* BTInquiryViewController.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = BTInquiryViewController.h; path = CocoaTouch/include/BTstack/BTInquiryViewController.h; sourceTree = "<group>"; };
|
||||
9C13C9FE10ECED6300B04243 /* BTInquiryViewController.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; name = BTInquiryViewController.m; path = CocoaTouch/src/BTInquiryViewController.m; sourceTree = "<group>"; };
|
||||
9C18015B108BAA7200824BE7 /* libusb-1.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libusb-1.0.dylib"; path = "/usr/local/lib/libusb-1.0.dylib"; sourceTree = "<absolute>"; };
|
||||
9C1813F71042FCCA00C68F09 /* mitm.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = mitm.c; path = example/mitm.c; sourceTree = "<group>"; };
|
||||
9C2071F210014D3200A07EA4 /* hci_transport_usb.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = hci_transport_usb.c; path = src/hci_transport_usb.c; sourceTree = "<group>"; };
|
||||
9C2169D112F9FB7000072B00 /* platform_iphone.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; name = platform_iphone.m; path = src/platform_iphone.m; sourceTree = "<group>"; };
|
||||
9C255D4911E0C59900CDD689 /* run_loop_embedded.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = run_loop_embedded.c; path = src/run_loop_embedded.c; sourceTree = "<group>"; };
|
||||
9C255D7611E0DD2C00CDD689 /* hci_transport_h4_stellaris.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = hci_transport_h4_stellaris.c; path = "../../TI/Stellarware/boards/dk-lm3s9b96/bt_init/hci_transport_h4_stellaris.c"; sourceTree = SOURCE_ROOT; };
|
||||
9C255DB511E10AEB00CDD689 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = debug.h; path = src/debug.h; sourceTree = "<group>"; };
|
||||
@ -95,7 +96,6 @@
|
||||
9C77E7501066680800F39DCF /* SpringBoardAccessExtension.mm */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.cpp.objcpp; name = SpringBoardAccessExtension.mm; path = SpringBoardAccess/SpringBoardAccessExtension.mm; sourceTree = "<group>"; };
|
||||
9C77E75310666B5D00F39DCF /* SpringBoardAccess.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = SpringBoardAccess.c; path = SpringBoardAccess/SpringBoardAccess.c; sourceTree = "<group>"; };
|
||||
9C77E75410666B5D00F39DCF /* SpringBoardAccess.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = SpringBoardAccess.h; path = SpringBoardAccess/SpringBoardAccess.h; sourceTree = "<group>"; };
|
||||
9C77E79110667F0600F39DCF /* platform_iphone.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = platform_iphone.c; path = src/platform_iphone.c; sourceTree = "<group>"; };
|
||||
9C77E7BC1066AC4100F39DCF /* control */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = control; path = SpringBoardAccess/control; sourceTree = "<group>"; };
|
||||
9C78A04A103C6734003B2950 /* Default_BTstack.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default_BTstack.png; path = resources/Default_BTstack.png; sourceTree = "<group>"; };
|
||||
9C78A04B103C6734003B2950 /* Default_BTstackActive.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default_BTstackActive.png; path = resources/Default_BTstackActive.png; sourceTree = "<group>"; };
|
||||
@ -114,6 +114,7 @@
|
||||
9C9485C41211D58300B66EF1 /* l2cap-throughput.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = "l2cap-throughput.c"; path = "example/l2cap-throughput.c"; sourceTree = "<group>"; };
|
||||
9C978672113DC04900380B3E /* ch.ringwald.BTstackTCP.plist */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.plist.xml; name = ch.ringwald.BTstackTCP.plist; path = resources/ch.ringwald.BTstackTCP.plist; sourceTree = "<group>"; };
|
||||
9C994B8E106BEEB700C70311 /* rfcomm.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = rfcomm.c; path = example/rfcomm.c; sourceTree = "<group>"; };
|
||||
9C9F1A3C122F02DD004E21AC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
9CA3C0900FB8B3C4005F48DE /* TODO.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = TODO.txt; sourceTree = "<group>"; };
|
||||
9CAA573610A5D87400D0E1A9 /* inquiry.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = inquiry.c; path = example/inquiry.c; sourceTree = "<group>"; };
|
||||
9CB9846A11BC32A800A2F346 /* sdp_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sdp_util.c; path = src/sdp_util.c; sourceTree = "<group>"; };
|
||||
@ -149,7 +150,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9C04B87A107D2BA7002A63D0 /* CoreFoundation.framework in Frameworks */,
|
||||
9C18015C108BAA7200824BE7 /* libusb-1.0.dylib in Frameworks */,
|
||||
9C9F1A3D122F02DD004E21AC /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -175,6 +176,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9CBE154810A354FF00597802 /* package.sh */,
|
||||
9CA3C0900FB8B3C4005F48DE /* TODO.txt */,
|
||||
9CEB4B7510715DC200DD5720 /* include */,
|
||||
9C77E4AD10634E3100F39DCF /* 3rdparty */,
|
||||
9C78A049103C671D003B2950 /* Resources */,
|
||||
@ -185,8 +187,8 @@
|
||||
C6A0FF2B0290797F04C91782 /* Documentation */,
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */,
|
||||
9CC152C61009052100223347 /* config.h */,
|
||||
9CA3C0900FB8B3C4005F48DE /* TODO.txt */,
|
||||
9C04B879107D2BA7002A63D0 /* CoreFoundation.framework */,
|
||||
9C9F1A3C122F02DD004E21AC /* Foundation.framework */,
|
||||
);
|
||||
name = project;
|
||||
sourceTree = "<group>";
|
||||
@ -224,8 +226,8 @@
|
||||
9C00F7301017ACC3008DAB17 /* socket_connection.c */,
|
||||
9C00F7311017ACC3008DAB17 /* socket_connection.h */,
|
||||
9C00F86210191097008DAB17 /* utils.c */,
|
||||
9C77E79110667F0600F39DCF /* platform_iphone.c */,
|
||||
9C6459DE1037554B0081A00B /* platform_iphone.h */,
|
||||
9C2169D112F9FB7000072B00 /* platform_iphone.m */,
|
||||
9CB9846A11BC32A800A2F346 /* sdp_util.c */,
|
||||
9CE7CDD711BFF5470096F5B1 /* sdp.c */,
|
||||
9CFFD48C11C4CD0100A37038 /* sdp.h */,
|
||||
@ -283,7 +285,6 @@
|
||||
9C77E4AD10634E3100F39DCF /* 3rdparty */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9C18015B108BAA7200824BE7 /* libusb-1.0.dylib */,
|
||||
9C77E4AE10634E3100F39DCF /* launch.h */,
|
||||
9C77E4AF10634E3100F39DCF /* libsubstrate.dylib */,
|
||||
9C77E4B010634E3100F39DCF /* README */,
|
||||
@ -400,7 +401,14 @@
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "project" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
English,
|
||||
Japanese,
|
||||
French,
|
||||
German,
|
||||
);
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* project */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
@ -437,7 +445,6 @@
|
||||
9C00F86510191097008DAB17 /* utils.c in Sources */,
|
||||
9C00F87410191130008DAB17 /* l2cap_signaling.c in Sources */,
|
||||
9CCE6CEA1025BD0000FCE9F4 /* hci.c in Sources */,
|
||||
9C77E79210667F0600F39DCF /* platform_iphone.c in Sources */,
|
||||
9CEB4F17107AAAEF00DD5720 /* run_loop_posix.c in Sources */,
|
||||
9C04B826107D1CED002A63D0 /* run_loop.c in Sources */,
|
||||
9C04B876107D2B7C002A63D0 /* run_loop_cocoa.m in Sources */,
|
||||
@ -445,6 +452,8 @@
|
||||
9CE7CDD811BFF5470096F5B1 /* sdp.c in Sources */,
|
||||
9C255D4A11E0C59900CDD689 /* run_loop_embedded.c in Sources */,
|
||||
9C3AED88122C201C008046F4 /* remote_device_db_iphone.m in Sources */,
|
||||
9C5E0F0E12DE39250013EF2C /* hci_transport_usb.c in Sources */,
|
||||
9C2169D212F9FB7000072B00 /* platform_iphone.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -521,6 +530,11 @@
|
||||
/sw/include,
|
||||
);
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = "-I/usr/local/include";
|
||||
OTHER_LDFLAGS = (
|
||||
"-L/usr/local/lib",
|
||||
"-lusb-1.0",
|
||||
);
|
||||
PREBINDING = NO;
|
||||
SDKROOT = macosx10.5;
|
||||
};
|
||||
@ -533,6 +547,11 @@
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
OTHER_CFLAGS = "-I/usr/local/include";
|
||||
OTHER_LDFLAGS = (
|
||||
"-L/usr/local/lib",
|
||||
"-lusb-1.0",
|
||||
);
|
||||
PREBINDING = NO;
|
||||
SDKROOT = macosx10.5;
|
||||
};
|
||||
@ -589,6 +608,11 @@
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = "-I/usr/local/include";
|
||||
OTHER_LDFLAGS = (
|
||||
"-L/usr/local/lib",
|
||||
"-lusb-1.0",
|
||||
);
|
||||
PREBINDING = NO;
|
||||
SDKROOT = iphoneos2.0;
|
||||
};
|
||||
|
@ -24,6 +24,7 @@ BTdaemon_SOURCES = $(libBTstack_SOURCES) \
|
||||
l2cap_signaling.c \
|
||||
$(remote_device_db_sources) \
|
||||
platform_iphone.m \
|
||||
rfcomm.c \
|
||||
sdp.c \
|
||||
$(springboard_access_sources)
|
||||
|
||||
|
@ -119,6 +119,11 @@ void bt_send_l2cap(uint16_t source_cid, uint8_t *data, uint16_t len){
|
||||
socket_connection_send_packet(btstack_connection, L2CAP_DATA_PACKET, source_cid, data, len);
|
||||
}
|
||||
|
||||
void bt_send_rfcomm(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
|
||||
// send
|
||||
socket_connection_send_packet(btstack_connection, RFCOMM_DATA_PACKET, rfcomm_cid, data, len);
|
||||
}
|
||||
|
||||
void bt_send_acl(uint8_t * data, uint16_t len){
|
||||
// send
|
||||
socket_connection_send_packet(btstack_connection, HCI_ACL_DATA_PACKET, 0, data, len);
|
||||
|
45
src/daemon.c
45
src/daemon.c
@ -51,6 +51,7 @@
|
||||
#include <btstack/btstack.h>
|
||||
#include <btstack/linked_list.h>
|
||||
#include <btstack/run_loop.h>
|
||||
#include <btstack/rfcomm.h>
|
||||
|
||||
#include "hci.h"
|
||||
#include "hci_dump.h"
|
||||
@ -127,8 +128,11 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
|
||||
bd_addr_t addr;
|
||||
uint16_t cid;
|
||||
uint16_t psm;
|
||||
uint16_t service_channel;
|
||||
uint16_t registration_id;
|
||||
uint16_t mtu;
|
||||
uint8_t reason;
|
||||
uint8_t rfcomm_channel;
|
||||
uint32_t service_record_handle;
|
||||
client_state_t *client;
|
||||
|
||||
@ -223,6 +227,36 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
|
||||
reason = packet[7];
|
||||
l2cap_decline_connection_internal(cid, reason);
|
||||
break;
|
||||
|
||||
case RFCOMM_CREATE_CHANNEL:
|
||||
bt_flip_addr(addr, &packet[3]);
|
||||
rfcomm_channel = packet[9];
|
||||
rfcomm_create_channel_internal( connection, &addr, rfcomm_channel );
|
||||
break;
|
||||
case RFCOMM_DISCONNECT:
|
||||
cid = READ_BT_16(packet, 3);
|
||||
reason = packet[5];
|
||||
rfcomm_disconnect_internal(cid);
|
||||
break;
|
||||
case RFCOMM_REGISTER_SERVICE:
|
||||
registration_id = READ_BT_16(packet, 3);
|
||||
mtu = READ_BT_16(packet, 5);
|
||||
rfcomm_register_service_internal(connection, registration_id, mtu);
|
||||
break;
|
||||
case RFCOMM_UNREGISTER_SERVICE:
|
||||
service_channel = READ_BT_16(packet, 3);
|
||||
rfcomm_unregister_service_internal(service_channel);
|
||||
break;
|
||||
case RFCOMM_ACCEPT_CONNECTION:
|
||||
cid = READ_BT_16(packet, 3);
|
||||
rfcomm_accept_connection_internal(cid);
|
||||
break;
|
||||
case RFCOMM_DECLINE_CONNECTION:
|
||||
cid = READ_BT_16(packet, 3);
|
||||
reason = packet[7];
|
||||
rfcomm_decline_connection_internal(cid);
|
||||
break;
|
||||
|
||||
case SDP_REGISTER_SERVICE_RECORD:
|
||||
printf("SDP_REGISTER_SERVICE_RECORD size %u\n", size);
|
||||
sdp_register_service_internal(connection, &packet[3]);
|
||||
@ -261,6 +295,10 @@ static int daemon_client_handler(connection_t *connection, uint16_t packet_type,
|
||||
// process l2cap packet...
|
||||
err = l2cap_send_internal(channel, data, length);
|
||||
break;
|
||||
case RFCOMM_DATA_PACKET:
|
||||
// process l2cap packet...
|
||||
err = rfcomm_send_internal(channel, data, length);
|
||||
break;
|
||||
case DAEMON_EVENT_PACKET:
|
||||
switch (data[0]) {
|
||||
case DAEMON_EVENT_CONNECTION_OPENED:
|
||||
@ -501,8 +539,13 @@ int main (int argc, char * const * argv){
|
||||
l2cap_register_packet_handler(daemon_packet_handler);
|
||||
timeout.process = daemon_no_connections_timeout;
|
||||
|
||||
#ifdef HAVE_RFCOMM
|
||||
printf("config.h: HAVE_RFCOMM\n");
|
||||
rfcomm_init();
|
||||
rfcomm_register_packet_handler(daemon_packet_handler);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SDP
|
||||
// init SDP
|
||||
sdp_init();
|
||||
// sdp_test();
|
||||
#endif
|
||||
|
@ -2,7 +2,7 @@
|
||||
FILE=../include/btstack/version.h
|
||||
REVISION=`svnversion | sed "s/\([0-9]*\).*/\1/"`
|
||||
MAJOR=0
|
||||
MINOR=2
|
||||
MINOR=3
|
||||
DATE=`date "+%Y-%m-%d_%H:%M:%S"`
|
||||
printf "// BTstack - version.h\n" > $FILE
|
||||
printf "// - generated by %s\n" $0>> $FILE
|
||||
|
@ -122,6 +122,13 @@ extern "C" {
|
||||
// unregister SDP Service Record
|
||||
#define SDP_UNREGISTER_SERVICE_RECORD 0x31
|
||||
|
||||
// RFCOMM "HCI" Commands
|
||||
#define RFCOMM_CREATE_CHANNEL 0x40
|
||||
#define RFCOMM_DISCONNECT 0x41
|
||||
#define RFCOMM_REGISTER_SERVICE 0x42
|
||||
#define RFCOMM_UNREGISTER_SERVICE 0x43
|
||||
#define RFCOMM_ACCEPT_CONNECTION 0x44
|
||||
#define RFCOMM_DECLINE_CONNECTION 0x45
|
||||
|
||||
//
|
||||
#define IS_COMMAND(packet, command) (READ_BT_16(packet,0) == command.opcode)
|
||||
|
@ -396,3 +396,29 @@ OPCODE(OGF_BTSTACK, SDP_UNREGISTER_SERVICE_RECORD), "4"
|
||||
// @param service record handle (32)
|
||||
};
|
||||
|
||||
// create rfcomm channel: @param bd_addr(48), channel (8)
|
||||
const hci_cmd_t rfcomm_create_channel = {
|
||||
OPCODE(OGF_BTSTACK, RFCOMM_CREATE_CHANNEL), "B1"
|
||||
};
|
||||
// disconnect rfcomm disconnect, @param rfcomm_cid(8), reason(8)
|
||||
const hci_cmd_t rfcomm_disconnect = {
|
||||
OPCODE(OGF_BTSTACK, RFCOMM_DISCONNECT), "21"
|
||||
};
|
||||
// register rfcomm service: @param registration id(16), mtu (16)
|
||||
const hci_cmd_t rfcomm_register_service = {
|
||||
OPCODE(OGF_BTSTACK, RFCOMM_REGISTER_SERVICE), "22"
|
||||
};
|
||||
// unregister rfcomm service, @param service_channel(16)
|
||||
const hci_cmd_t rfcomm_unregister_service = {
|
||||
OPCODE(OGF_BTSTACK, RFCOMM_UNREGISTER_SERVICE), "2"
|
||||
};
|
||||
// accept connection @param bd_addr(48), rfcomm_cid (16)
|
||||
const hci_cmd_t rfcomm_accept_connection = {
|
||||
OPCODE(OGF_BTSTACK, RFCOMM_ACCEPT_CONNECTION), "2"
|
||||
// @param source cid (16)
|
||||
};
|
||||
// decline rfcomm disconnect,@param bd_addr(48), rfcomm cid (16), reason(8)
|
||||
const hci_cmd_t rfcomm_decline_connection = {
|
||||
OPCODE(OGF_BTSTACK, RFCOMM_DECLINE_CONNECTION), "21"
|
||||
// @param source cid (16), reason(8)
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user