diff --git a/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.pbxproj b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.pbxproj new file mode 100644 index 0000000..706612b --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.pbxproj @@ -0,0 +1,378 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 193A240C1A2413310051610A /* com_error.c in Sources */ = {isa = PBXBuildFile; fileRef = 193A24021A2413310051610A /* com_error.c */; }; + 193A240D1A2413310051610A /* com_iface.c in Sources */ = {isa = PBXBuildFile; fileRef = 193A24031A2413310051610A /* com_iface.c */; }; + 193A240E1A2413310051610A /* com_pterm.c in Sources */ = {isa = PBXBuildFile; fileRef = 193A24051A2413310051610A /* com_pterm.c */; }; + 193A24101A2413310051610A /* PseudoTermController.m in Sources */ = {isa = PBXBuildFile; fileRef = 193A24091A2413310051610A /* PseudoTermController.m */; }; + 193A24161A2413A80051610A /* DFUController.m in Sources */ = {isa = PBXBuildFile; fileRef = 193A24131A2413A80051610A /* DFUController.m */; }; + 193A24171A2413A80051610A /* DFUTargetAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 193A24151A2413A80051610A /* DFUTargetAdapter.m */; }; + 193A241A1A2413E00051610A /* IntelHex2BinConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 193A24191A2413E00051610A /* IntelHex2BinConverter.m */; }; + 193A241D1A2414AD0051610A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 193A241C1A2414AD0051610A /* AppDelegate.m */; }; + 193A24201A2414E80051610A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 193A241E1A2414E80051610A /* MainMenu.xib */; }; + 193A24241A2415420051610A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 193A24211A2415420051610A /* main.m */; }; + 193A24251A2415420051610A /* RBL_DFU-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 193A24221A2415420051610A /* RBL_DFU-Info.plist */; }; + 193A242A1A2415610051610A /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 193A24261A2415610051610A /* Credits.rtf */; }; + 193A242B1A2415610051610A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 193A24281A2415610051610A /* InfoPlist.strings */; }; + 1998785619922F0100BDC451 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1998785519922F0100BDC451 /* IOKit.framework */; }; + 29F401A1163B510F007BEE39 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29F401A0163B510F007BEE39 /* Cocoa.framework */; }; + 29F401C2163B514A007BEE39 /* IOBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29F401C1163B514A007BEE39 /* IOBluetooth.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 193A24021A2413310051610A /* com_error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = com_error.c; path = RBL_DFU/PesoduTerm/com_error.c; sourceTree = SOURCE_ROOT; }; + 193A24031A2413310051610A /* com_iface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = com_iface.c; path = RBL_DFU/PesoduTerm/com_iface.c; sourceTree = SOURCE_ROOT; }; + 193A24041A2413310051610A /* com_iface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = com_iface.h; path = RBL_DFU/PesoduTerm/com_iface.h; sourceTree = SOURCE_ROOT; }; + 193A24051A2413310051610A /* com_pterm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = com_pterm.c; path = RBL_DFU/PesoduTerm/com_pterm.c; sourceTree = SOURCE_ROOT; }; + 193A24061A2413310051610A /* com_pterm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = com_pterm.h; path = RBL_DFU/PesoduTerm/com_pterm.h; sourceTree = SOURCE_ROOT; }; + 193A24081A2413310051610A /* PseudoTermController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PseudoTermController.h; path = RBL_DFU/PesoduTerm/PseudoTermController.h; sourceTree = SOURCE_ROOT; }; + 193A24091A2413310051610A /* PseudoTermController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PseudoTermController.m; path = RBL_DFU/PesoduTerm/PseudoTermController.m; sourceTree = SOURCE_ROOT; }; + 193A24121A2413A80051610A /* DFUController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFUController.h; path = RBL_DFU/DFU/DFUController.h; sourceTree = SOURCE_ROOT; }; + 193A24131A2413A80051610A /* DFUController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DFUController.m; path = RBL_DFU/DFU/DFUController.m; sourceTree = SOURCE_ROOT; }; + 193A24141A2413A80051610A /* DFUTargetAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFUTargetAdapter.h; path = RBL_DFU/DFU/DFUTargetAdapter.h; sourceTree = SOURCE_ROOT; }; + 193A24151A2413A80051610A /* DFUTargetAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DFUTargetAdapter.m; path = RBL_DFU/DFU/DFUTargetAdapter.m; sourceTree = SOURCE_ROOT; }; + 193A24181A2413E00051610A /* IntelHex2BinConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IntelHex2BinConverter.h; path = RBL_DFU/hex2bin/IntelHex2BinConverter.h; sourceTree = SOURCE_ROOT; }; + 193A24191A2413E00051610A /* IntelHex2BinConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IntelHex2BinConverter.m; path = RBL_DFU/hex2bin/IntelHex2BinConverter.m; sourceTree = SOURCE_ROOT; }; + 193A241B1A2414AD0051610A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = RBL_DFU/AppDelegate.h; sourceTree = SOURCE_ROOT; }; + 193A241C1A2414AD0051610A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = RBL_DFU/AppDelegate.m; sourceTree = SOURCE_ROOT; }; + 193A241F1A2414E80051610A /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = RBL_DFU/en.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; }; + 193A24211A2415420051610A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RBL_DFU/main.m; sourceTree = SOURCE_ROOT; }; + 193A24221A2415420051610A /* RBL_DFU-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "RBL_DFU-Info.plist"; path = "RBL_DFU/RBL_DFU-Info.plist"; sourceTree = SOURCE_ROOT; }; + 193A24231A2415420051610A /* RBL_DFU-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RBL_DFU-Prefix.pch"; path = "RBL_DFU/RBL_DFU-Prefix.pch"; sourceTree = SOURCE_ROOT; }; + 193A24271A2415610051610A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = RBL_DFU/en.lproj/Credits.rtf; sourceTree = SOURCE_ROOT; }; + 193A24291A2415610051610A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = RBL_DFU/en.lproj/InfoPlist.strings; sourceTree = SOURCE_ROOT; }; + 1998785519922F0100BDC451 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + 29F4019C163B510F007BEE39 /* RBL_DFU.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RBL_DFU.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 29F401A0163B510F007BEE39 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 29F401A3163B510F007BEE39 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 29F401A4163B510F007BEE39 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 29F401A5163B510F007BEE39 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 29F401C1163B514A007BEE39 /* IOBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetooth.framework; path = System/Library/Frameworks/IOBluetooth.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 29F40199163B510F007BEE39 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 29F401C2163B514A007BEE39 /* IOBluetooth.framework in Frameworks */, + 29F401A1163B510F007BEE39 /* Cocoa.framework in Frameworks */, + 1998785619922F0100BDC451 /* IOKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 19A115AC19A07ACD0014B55A /* PesoduTerm */ = { + isa = PBXGroup; + children = ( + 193A24021A2413310051610A /* com_error.c */, + 193A24031A2413310051610A /* com_iface.c */, + 193A24041A2413310051610A /* com_iface.h */, + 193A24051A2413310051610A /* com_pterm.c */, + 193A24061A2413310051610A /* com_pterm.h */, + 193A24081A2413310051610A /* PseudoTermController.h */, + 193A24091A2413310051610A /* PseudoTermController.m */, + ); + name = PesoduTerm; + sourceTree = ""; + }; + 19A1E507198B6676003B3B8F /* hex2bin */ = { + isa = PBXGroup; + children = ( + 193A24181A2413E00051610A /* IntelHex2BinConverter.h */, + 193A24191A2413E00051610A /* IntelHex2BinConverter.m */, + ); + name = hex2bin; + sourceTree = ""; + }; + 19A1E50B198B66B5003B3B8F /* DFU */ = { + isa = PBXGroup; + children = ( + 193A24121A2413A80051610A /* DFUController.h */, + 193A24131A2413A80051610A /* DFUController.m */, + 193A24141A2413A80051610A /* DFUTargetAdapter.h */, + 193A24151A2413A80051610A /* DFUTargetAdapter.m */, + ); + name = DFU; + sourceTree = ""; + }; + 29F40191163B510F007BEE39 = { + isa = PBXGroup; + children = ( + 29F401A6163B510F007BEE39 /* RBL_DFU */, + 29F4019F163B510F007BEE39 /* Frameworks */, + 29F4019D163B510F007BEE39 /* Products */, + ); + sourceTree = ""; + }; + 29F4019D163B510F007BEE39 /* Products */ = { + isa = PBXGroup; + children = ( + 29F4019C163B510F007BEE39 /* RBL_DFU.app */, + ); + name = Products; + sourceTree = ""; + }; + 29F4019F163B510F007BEE39 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1998785519922F0100BDC451 /* IOKit.framework */, + 29F401C1163B514A007BEE39 /* IOBluetooth.framework */, + 29F401A0163B510F007BEE39 /* Cocoa.framework */, + 29F401A2163B510F007BEE39 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 29F401A2163B510F007BEE39 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 29F401A3163B510F007BEE39 /* AppKit.framework */, + 29F401A4163B510F007BEE39 /* CoreData.framework */, + 29F401A5163B510F007BEE39 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 29F401A6163B510F007BEE39 /* RBL_DFU */ = { + isa = PBXGroup; + children = ( + 193A241E1A2414E80051610A /* MainMenu.xib */, + 193A241B1A2414AD0051610A /* AppDelegate.h */, + 193A241C1A2414AD0051610A /* AppDelegate.m */, + 19A115AC19A07ACD0014B55A /* PesoduTerm */, + 19A1E50B198B66B5003B3B8F /* DFU */, + 19A1E507198B6676003B3B8F /* hex2bin */, + 29F401A7163B510F007BEE39 /* Supporting Files */, + ); + name = RBL_DFU; + path = SimpleControls; + sourceTree = ""; + }; + 29F401A7163B510F007BEE39 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 193A24261A2415610051610A /* Credits.rtf */, + 193A24281A2415610051610A /* InfoPlist.strings */, + 193A24211A2415420051610A /* main.m */, + 193A24221A2415420051610A /* RBL_DFU-Info.plist */, + 193A24231A2415420051610A /* RBL_DFU-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 29F4019B163B510F007BEE39 /* RBL_DFU */ = { + isa = PBXNativeTarget; + buildConfigurationList = 29F401BA163B510F007BEE39 /* Build configuration list for PBXNativeTarget "RBL_DFU" */; + buildPhases = ( + 29F40198163B510F007BEE39 /* Sources */, + 29F40199163B510F007BEE39 /* Frameworks */, + 29F4019A163B510F007BEE39 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RBL_DFU; + productName = BLETest; + productReference = 29F4019C163B510F007BEE39 /* RBL_DFU.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29F40193163B510F007BEE39 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = RedBearLab; + }; + buildConfigurationList = 29F40196163B510F007BEE39 /* Build configuration list for PBXProject "RBL_DFU" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 29F40191163B510F007BEE39; + productRefGroup = 29F4019D163B510F007BEE39 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 29F4019B163B510F007BEE39 /* RBL_DFU */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 29F4019A163B510F007BEE39 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 193A24201A2414E80051610A /* MainMenu.xib in Resources */, + 193A242B1A2415610051610A /* InfoPlist.strings in Resources */, + 193A242A1A2415610051610A /* Credits.rtf in Resources */, + 193A24251A2415420051610A /* RBL_DFU-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 29F40198163B510F007BEE39 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 193A241D1A2414AD0051610A /* AppDelegate.m in Sources */, + 193A240D1A2413310051610A /* com_iface.c in Sources */, + 193A24161A2413A80051610A /* DFUController.m in Sources */, + 193A240C1A2413310051610A /* com_error.c in Sources */, + 193A240E1A2413310051610A /* com_pterm.c in Sources */, + 193A24101A2413310051610A /* PseudoTermController.m in Sources */, + 193A241A1A2413E00051610A /* IntelHex2BinConverter.m in Sources */, + 193A24241A2415420051610A /* main.m in Sources */, + 193A24171A2413A80051610A /* DFUTargetAdapter.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 193A241E1A2414E80051610A /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 193A241F1A2414E80051610A /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; + 193A24261A2415610051610A /* Credits.rtf */ = { + isa = PBXVariantGroup; + children = ( + 193A24271A2415610051610A /* en */, + ); + name = Credits.rtf; + sourceTree = ""; + }; + 193A24281A2415610051610A /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 193A24291A2415610051610A /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 29F401B8163B510F007BEE39 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 29F401B9163B510F007BEE39 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + }; + name = Release; + }; + 29F401BB163B510F007BEE39 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "RBL_DFU/RBL_DFU-Prefix.pch"; + INFOPLIST_FILE = "RBL_DFU/RBL_DFU-Info.plist"; + PRODUCT_NAME = RBL_DFU; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 29F401BC163B510F007BEE39 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "RBL_DFU/RBL_DFU-Prefix.pch"; + INFOPLIST_FILE = "RBL_DFU/RBL_DFU-Info.plist"; + PRODUCT_NAME = RBL_DFU; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 29F40196163B510F007BEE39 /* Build configuration list for PBXProject "RBL_DFU" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29F401B8163B510F007BEE39 /* Debug */, + 29F401B9163B510F007BEE39 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 29F401BA163B510F007BEE39 /* Build configuration list for PBXNativeTarget "RBL_DFU" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 29F401BB163B510F007BEE39 /* Debug */, + 29F401BC163B510F007BEE39 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29F40193163B510F007BEE39 /* Project object */; +} diff --git a/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..dab1277 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcshareddata/RBL_DFU.xccheckout b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcshareddata/RBL_DFU.xccheckout new file mode 100644 index 0000000..e11ff93 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcshareddata/RBL_DFU.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + F82BD996-878C-4A12-AF93-E4A9E38B681C + IDESourceControlProjectName + RBL_DFU + IDESourceControlProjectOriginsDictionary + + 9B835C21074C5F6D029A10E5AC5E6BD03C9CE89E + https://bitbucket.org/redbear/rbl_sdk.git + + IDESourceControlProjectPath + iOS/Examples/DFU_Mac/RBL_DFU.xcodeproj + IDESourceControlProjectRelativeInstallPathDictionary + + 9B835C21074C5F6D029A10E5AC5E6BD03C9CE89E + ../../../../.. + + IDESourceControlProjectURL + https://bitbucket.org/redbear/rbl_sdk.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + 9B835C21074C5F6D029A10E5AC5E6BD03C9CE89E + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 9B835C21074C5F6D029A10E5AC5E6BD03C9CE89E + IDESourceControlWCCName + rbl_sdk + + + + diff --git a/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcshareddata/SimpleControls.xccheckout b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcshareddata/SimpleControls.xccheckout new file mode 100644 index 0000000..ed799b4 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcshareddata/SimpleControls.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 4CA390DF-0F7B-4A13-A166-53E79EEC5E23 + IDESourceControlProjectName + SimpleControls + IDESourceControlProjectOriginsDictionary + + 9B835C21074C5F6D029A10E5AC5E6BD03C9CE89E + https://bitbucket.org/redbear/rbl_sdk.git + + IDESourceControlProjectPath + iOS/Examples/SimpleControls_Mac/SimpleControls.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 9B835C21074C5F6D029A10E5AC5E6BD03C9CE89E + ../../../../.. + + IDESourceControlProjectURL + https://bitbucket.org/redbear/rbl_sdk.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + 9B835C21074C5F6D029A10E5AC5E6BD03C9CE89E + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 9B835C21074C5F6D029A10E5AC5E6BD03C9CE89E + IDESourceControlWCCName + rbl_sdk + + + + diff --git a/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcuserdata/redbear.xcuserdatad/UserInterfaceState.xcuserstate b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcuserdata/redbear.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..ca1a062 Binary files /dev/null and b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcuserdata/redbear.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcuserdata/redbear.xcuserdatad/WorkspaceSettings.xcsettings b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcuserdata/redbear.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..659c876 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/project.xcworkspace/xcuserdata/redbear.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + + SnapshotAutomaticallyBeforeSignificantChanges + + + diff --git a/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/xcuserdata/redbear.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/xcuserdata/redbear.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..7eb5c51 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/xcuserdata/redbear.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/xcuserdata/redbear.xcuserdatad/xcschemes/SimpleControls.xcscheme b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/xcuserdata/redbear.xcuserdatad/xcschemes/SimpleControls.xcscheme new file mode 100644 index 0000000..0da8c9c --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/xcuserdata/redbear.xcuserdatad/xcschemes/SimpleControls.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/xcuserdata/redbear.xcuserdatad/xcschemes/xcschememanagement.plist b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/xcuserdata/redbear.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..8e71acf --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU.xcodeproj/xcuserdata/redbear.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + SimpleControls.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 29F4019B163B510F007BEE39 + + primary + + + + + diff --git a/MacOSX/DFU_Mac/RBL_DFU/AppDelegate.h b/MacOSX/DFU_Mac/RBL_DFU/AppDelegate.h new file mode 100644 index 0000000..3ca4bd1 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/AppDelegate.h @@ -0,0 +1,35 @@ +// +// AppDelegate.h +// SimpleControls +// +// Created by Cheong on 27/10/12. +// Copyright (c) 2012 RedBearLab. All rights reserved. +// + +#import +#import "IntelHex2BinConverter.h" +#import "DFUController.h" +#import "PseudoTermController.h" + +@interface AppDelegate : NSObject +{ + IBOutlet NSButton *btnUpload; + IBOutlet NSButton *btnSelectFile; + IBOutlet NSButton *btnSketch; + IBOutlet NSProgressIndicator *indConnect; + IBOutlet NSTextField *txtFile; + IBOutlet NSProgressIndicator *progress; +} + +@property (assign) IBOutlet NSWindow *window; + +@property (strong, nonatomic) CBCentralManager *bluetoothManager; +@property (strong, nonatomic) NSMutableArray *peripherals; +@property (strong, nonatomic) CBPeripheral *selectedPeripheral; +@property DFUController *dfuController; +@property PseudoTermController *PseudoTermApp; +@property BOOL isUploading; +@property BOOL isComportOpen; +@property (nonatomic) bool FirmwareReady; + +@end diff --git a/MacOSX/DFU_Mac/RBL_DFU/AppDelegate.m b/MacOSX/DFU_Mac/RBL_DFU/AppDelegate.m new file mode 100644 index 0000000..ea4628d --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/AppDelegate.m @@ -0,0 +1,426 @@ +// +// AppDelegate.m +// SimpleControls +// +// Created by Cheong on 27/10/12. +// Copyright (c) 2012 RedBearLab. All rights reserved. +// + +#import "AppDelegate.h" + +@implementation AppDelegate + +@synthesize bluetoothManager; +@synthesize peripherals; +@synthesize selectedPeripheral; +@synthesize dfuController; +@synthesize PseudoTermApp; +@synthesize FirmwareReady = _FirmwareReady; + +NSTimer *repeatTimer; + +- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)application +{ + return YES; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + dfuController = [[DFUController alloc] initWithDelegate:self]; + + bluetoothManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil]; + + //virtualComport = [[VirtualComport alloc] initWithDelegate:self]; + PseudoTermApp = [[PseudoTermController alloc] initWithDelegate:self]; + + self.isUploading = NO; + self.isComportOpen = NO; + self.FirmwareReady = NO; + + //[PseudoTermApp initPseudoTerm]; + //repeatTimer = [NSTimer scheduledTimerWithTimeInterval:(float)1.0 target:self selector:@selector(autoUpload:) userInfo:nil repeats:YES]; + //[btnSketch setHidden:YES]; +} + +- (void) autoUpload:(NSTimer *)timer +{ + if(self.FirmwareReady) + { + NSLog(@"autoUpload"); + [repeatTimer invalidate]; + + [self btnUpload:btnUpload]; + } +} + +- (void) setFirmwareReady:(bool)isFirmwareReady +{ + _FirmwareReady = isFirmwareReady; + + if(isFirmwareReady) + { + btnUpload.enabled = true; + btnUpload.title = @"Upload"; + } + else + { + btnUpload.enabled = false; + btnUpload.title = @"Upload"; + } +} + +- (IBAction)btnSketch:(id)sender +{ + if(!self.isComportOpen) + { + self.FirmwareReady = NO; + //[virtualComport OpenSerialPort:"/tmp/tty.RBL-BLE1"]; + [PseudoTermApp initPseudoTerm]; + repeatTimer = [NSTimer scheduledTimerWithTimeInterval:(float)1.0 target:self selector:@selector(autoUpload:) userInfo:nil repeats:YES]; + } + else + { + //[virtualComport CloseSerialPort:NO]; + [PseudoTermApp closePseudoTerm:NO]; + [repeatTimer invalidate]; + } +} + +- (IBAction)btnSelectFile:(id)sender +{ + NSLog(@"Select file"); + + // Create a File Open Dialog class. + NSOpenPanel *panel = [NSOpenPanel openPanel]; + + // Set array of file types + NSArray *fileTypesArray; + fileTypesArray = [NSArray arrayWithObjects:@"hex", @"bin", nil]; + + // Enable options in the dialog. + [panel setCanChooseFiles:YES]; + [panel setCanChooseDirectories:NO]; + [panel setAllowsMultipleSelection:NO]; // yes if more than one dir is allowed + [panel setAllowedFileTypes:fileTypesArray]; + [panel setAllowsOtherFileTypes:YES]; + + if([panel runModal] == NSFileHandlingPanelOKButton) + { + NSArray *files = [panel URLs]; + + [txtFile setStringValue:(NSString *)[[files objectAtIndex:0] filePathURL]]; + NSURL *url = [[files objectAtIndex:0] filePathURL]; + NSLog(@"File URL: %@", url); + + self.FirmwareReady = YES; + [dfuController setFirmwareURL:url]; + } + else + { + NSLog(@"Select file canceled"); + self.FirmwareReady = NO; + } +} + +- (IBAction)btnUpload:(id)sender +{ + if (!self.isUploading) + { + btnUpload.enabled = false; + btnUpload.title=@"Scanning"; + + [self findBLEPeripherals:2]; + + [NSTimer scheduledTimerWithTimeInterval:(float)3.0 target:self selector:@selector(connectionTimer:) userInfo:nil repeats:NO]; + + [indConnect startAnimation:self]; + } + else + { + btnUpload.title=@"Upload"; + btnUpload.enabled = true; + [dfuController cancelTransfer]; + } +} + +- (int) findBLEPeripherals:(int) timeout +{ + if (bluetoothManager.state != CBCentralManagerStatePoweredOn) + { + NSLog(@"CoreBluetooth not correctly initialized !\r\n"); + return -1; + } + + [bluetoothManager scanForPeripheralsWithServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:@DFU_SERVICE_UUID]] options:nil]; // Start scanning + + [NSTimer scheduledTimerWithTimeInterval:(float)timeout target:self selector:@selector(scanTimer:) userInfo:nil repeats:NO]; + + NSLog(@"scanForPeripheralsWith DFU Services"); + + return 0; // Started scanning OK ! +} + +- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI +{ + if (!self.peripherals) + { + self.peripherals = [[NSMutableArray alloc] initWithObjects:peripheral,nil]; + } + else + { + [self.peripherals addObject:peripheral]; + } + + NSLog(@"didDiscoverPeripheral"); +} + +- (void) scanTimer:(NSTimer *)timer +{ + NSLog(@"Stopped Scanning"); + [bluetoothManager stopScan]; + + NSLog(@"Known peripherals : %lu",(unsigned long)[self.peripherals count]); + if([self.peripherals count] != 0) + { + [self printPeripheralInfo]; + } + else + { + btnUpload.title=@"Upload"; + btnUpload.enabled = true; + [indConnect stopAnimation:self]; + } +} + +- (void) printPeripheralInfo +{ + CBPeripheral *p = [self.peripherals objectAtIndex:0]; + if (p.UUID != NULL) + { + printf("------------------------------------\n"); + printf("Peripheral Info :\n"); + CFStringRef s = CFUUIDCreateString(NULL, p.UUID); + printf("UUID : %s\n",CFStringGetCStringPtr(s, 0)); + printf("Name : %s\n",[p.name cStringUsingEncoding:NSStringEncodingConversionAllowLossy]); + printf("-------------------------------------\r\n"); + } + else + { + [indConnect stopAnimation:self]; + btnUpload.title=@"Upload"; + btnUpload.enabled = true; + printf("UUID : NULL\n"); + } +} + +-(void) connectionTimer:(NSTimer *)timer +{ + if (self.peripherals.count > 0) + { + bluetoothManager.delegate = self; + + // Set the peripheral + dfuController.peripheral = [self.peripherals objectAtIndex:0]; + selectedPeripheral = [self.peripherals objectAtIndex:0]; + + NSLog(@"Connecting"); + btnUpload.title=@"Connecting"; + + [bluetoothManager connectPeripheral:selectedPeripheral options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]]; + } + else + { + [indConnect stopAnimation:self]; + } +} + +- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral +{ + btnUpload.title=@"Connected"; + + // Peripheral has connected. Discover required services + [dfuController didConnect]; + + [indConnect stopAnimation:self]; +} + +-(void)didChangeState:(DFUControllerState) state; +{ + // Scanner uses other queue to send events. We must edit UI in the main queue + dispatch_async(dispatch_get_main_queue(), ^{ + if (state == IDLE) + { + self.isUploading= YES; + + btnUpload.title=@"Uploading"; + btnUpload.enabled = true; + + [dfuController startTransfer]; + } + }); +} + +-(void)didUpdateProgress:(float)percent +{ + [progress setDoubleValue:percent]; + if(percent ==0.0) + { + [progress setHidden:YES]; + } + else + { + [progress setHidden:NO]; + } +} + +-(void)didFinishTransfer +{ + NSLog(@"Transfer finished!"); + self.isUploading = NO; + self.FirmwareReady = NO; + btnUpload.title=@"Upload"; +} + +-(void)didCancelTransfer +{ + NSLog(@"Transfer cancelled!"); + self.isUploading = NO; + self.FirmwareReady = NO; + btnUpload.title=@"Upload"; +} + +- (void)centralManagerDidUpdateState:(CBCentralManager *)central +{ + if (central.state == CBCentralManagerStatePoweredOn) { + // TODO + } + else + { + // TODO + NSLog(@"Bluetooth not ON"); + } +} + +- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error +{ + // Notify DFU controller about link loss + [self.dfuController didDisconnect:error]; +} + +-(void)didDisconnect:(NSError *)error +{ + NSLog(@"Transfer terminated!"); + self.isUploading = NO; + self.FirmwareReady = NO; + btnUpload.title=@"Upload"; +} + +-(void)didErrorOccurred:(DFUTargetResponse)error +{ + NSLog(@"Error occurred: %d", error); + self.isUploading = NO; + self.FirmwareReady = NO; + btnUpload.title=@"Upload"; + + NSString* message = nil; + switch (error) + { + case CRC_ERROR: + message = @"CRC error"; + break; + + case DATA_SIZE_EXCEEDS_LIMIT: + message = @"Data size exceeds limit"; + break; + + case INVALID_STATE: + message = @"Device is in the invalid state"; + break; + + case NOT_SUPPORTED: + message = @"Operation not supported. Image file may be to large."; + break; + + case OPERATION_FAILED: + message = @"Operation failed"; + break; + + case DEVICE_NOT_SUPPORTED: + message = @"Device is not supported. Check if it is in the DFU state."; + [bluetoothManager cancelPeripheralConnection:selectedPeripheral]; + selectedPeripheral = nil; + break; + + default: + message = @"Unknown error."; + break; + } + + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:message]; + [alert runModal]; + NSLog(@"%@", message); +} + +- (void) didOpenComport:(int) status +{ + if(status == 0) + { + NSLog(@"didOpenComport successfully."); + + btnSelectFile.enabled = false; + btnSketch.title = @"Disassociate"; + btnUpload.title = @"Receiving"; + self.isComportOpen = YES; + } + else if(status == -1) + { + NSLog(@"Create comport error!"); + } + else if(status == -2) + { + [PseudoTermApp closePseudoTerm:NO]; + NSLog(@"Create link error!"); + } + else + { + NSLog(@"Unknown error!"); + } +} + +- (void) didReceiveData:(NSData *) FirmwareData status:(bool) status +{ + if(YES == status) + { + NSLog(@"didReceiveData"); + + [dfuController setFirmwareBuffer:FirmwareData]; + + //[virtualComport CloseSerialPort:YES]; + [PseudoTermApp closePseudoTerm:YES]; + } + else + { + NSLog(@"Cancel receiving firmware"); + } +} + +- (void) didCloseComport:(bool) status +{ + NSLog(@"didCloseComport"); + btnSelectFile.enabled = true; + btnSketch.title = @"Associate"; + + self.isComportOpen = NO; + + if(status == YES) + { + self.FirmwareReady = YES; + } + else + { + self.FirmwareReady = NO; + } +} + +@end diff --git a/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUController.h b/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUController.h new file mode 100644 index 0000000..43bab3e --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUController.h @@ -0,0 +1,108 @@ +// +// DFUControllerStateMachine.h +// nRF Loader +// +// Created by Ole Morten on 10/22/13. +// Copyright (c) 2013 Nordic Semiconductor. All rights reserved. +// + +#import +#import "DFUTargetAdapter.h" + +typedef enum +{ + INIT, //0 + DISCOVERING, //1 + IDLE, //2 + SEND_NOTIFICATION_REQUEST, //3 + SEND_START_COMMAND, //4 + SEND_RECEIVE_COMMAND, //5 + SEND_FIRMWARE_DATA, //6 + SEND_VALIDATE_COMMAND, //7 + SEND_RESET, //8 + WAIT_RECEIPT, //9 + FINISHED, //10 + CANCELED, //11 + ERROR, //12 +} DFUControllerState; + + +@protocol DFUControllerDelegate +/*! + * @brief Invoked when the DFU controller has changed its state. + * @param state the new state of the controller + */ +- (void) didChangeState:(DFUControllerState) state; +/*! + * @brief Called when upload progress has changed. This method is invoked after each packet has been added to sending queue, it does not mean that it was really transmitted. + * As the Central Manager is created with custom event queue (see ScannerViewController.m -> viewDidLoad) + * this method must dispatch asynch request to the main queue in order to update UI. + * @param progress the current progress, float value from 0 to 1 where 1 means that the last byte has been added to the queue + */ +- (void) didUpdateProgress:(float) progress; +/*! + * @brief Invoked when the DFU process has been completed and the RESET AND ACTIVATE commang has been send to the peripheral. + * As the Central Manager is created with custom event queue (see ScannerViewController.m -> viewDidLoad) + * this method must dispatch asynch request to the main queue in order to update UI. + */ +- (void) didFinishTransfer; +/*! + * @brief Called just after invoking cancelTransfer. The RESET command will be send just after it. + * As the Central Manager is created with custom event queue (see ScannerViewController.m -> viewDidLoad) + * this method must dispatch asynch request to the main queue in order to update UI. + */ +- (void) didCancelTransfer; +/*! + * Invoked when the response recieved to Control Point characteristic is other than SUCCESS. + * @param error the status returned from the peripheral + */ +- (void) didErrorOccurred:(DFUTargetResponse) error; +/*! + * @brief Called when the connection has been terminated unless the firmware transfer was finished, cancelled of has failed. In + * The three later cases the (void)didFinishedTransfer, (void)didCancelTransfer, (void)didErrorOccurred:(DFUTargetResponse)error will be called. + */ +- (void) didDisconnect:(NSError *) error; +@end + +@interface DFUController : NSObject +@property (strong, nonatomic) id delegate; + +@property (copy, nonatomic) NSString *appName; +@property (assign, nonatomic) unsigned long appSize; +@property (readonly, nonatomic) unsigned long binSize; +@property (readonly, nonatomic) NSTimeInterval uploadInterval; + +@property (copy, nonatomic) NSString *targetName; + ++ (CBUUID *) serviceUUID; + +- (DFUController *) initWithDelegate:(id) delegate; +- (NSString *) stringFromState:(DFUControllerState) state; + +- (void) setPeripheral:(CBPeripheral *)peripheral; +- (void) setFirmwareURL:(NSURL *) URL; +- (void) setFirmwareBuffer:(NSData *) fwData; + +/*! + * @brief This method must be invoked by Central Manager Delegate when the device has connected to the target peripheral. + */ +- (void) didConnect; +/*! + * @brief This method must be invoked by Central Manager Delegate when the device has disconnected from the target peripheral. + */ +- (void) didDisconnect:(NSError *) error; + +/*! + * @brief Starts the DFU transfer process. The peripheral must be connected and services & characteristics must be discovered before calling this method. + */ +- (void) startTransfer; +/*! + * @brief Pauses the transfer. + * @warning This operation is not implemented. + */ +- (void) pauseTransfer; +/*! + * @brief Cancels the transfer and resets the peripheral. The previous application or a DFU bootloader will be started on the target device. + */ +- (void) cancelTransfer; +@end diff --git a/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUController.m b/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUController.m new file mode 100644 index 0000000..ed40a4a --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUController.m @@ -0,0 +1,393 @@ +// +// DFUControllerStateMachine.m +// nRF Loader +// +// Created by Ole Morten on 10/22/13. +// Copyright (c) 2013 Nordic Semiconductor. All rights reserved. +// + +#import "DFUController.h" +#import "IntelHex2BinConverter.h" +#import "string.h" + +#define DFUCONTROLLER_MAX_PACKET_SIZE 20 + +@interface DFUController ( ) +@property (nonatomic) DFUControllerState state; +@property DFUTargetAdapter *target; + +@property NSData *firmwareData; +@property NSUInteger firmwareDataBytesSent; +@property uint16_t notificationPacketInterval; + +@property (nonatomic) float progress; +@property (strong, nonatomic) NSDate* startDate; + +@end + +@implementation DFUController +@synthesize state = _state; +@synthesize delegate = _delegate; +@synthesize uploadInterval = _uploadInterval; + ++ (CBUUID *) serviceUUID +{ + return [[DFUTargetAdapter class] serviceUUID]; +} + +- (DFUController *) initWithDelegate:(id) delegate +{ + if (self = [super init]) + { + _state = INIT; + _delegate = delegate; + + _firmwareDataBytesSent = 0; + + _appName = @"-"; + _appSize = 0; + + _targetName = @"-"; + + _progress = 0; + + } + return self; +} + +- (void) setPeripheral:(CBPeripheral *)peripheral +{ + NSLog(@"DFU Controller setPeripherl"); + self.targetName = peripheral.name; + + self.target = [[DFUTargetAdapter alloc] initWithDelegate:self]; + self.target.peripheral = peripheral; +} + +- (void) setState:(DFUControllerState)newState +{ + @synchronized(self) + { + DFUControllerState oldState = _state; + _state = newState; + NSLog(@"State changed from %d to %d.", oldState, newState); + + if (newState == INIT) + { + self.progress = 0; + self.firmwareDataBytesSent = 0; + } + + [self.delegate didChangeState:newState]; + } +} + +- (DFUControllerState) state +{ + return _state; +} + +- (NSString *) stringFromState:(DFUControllerState) state +{ + switch (state) + { + case INIT: + return @"Init"; + + case DISCOVERING: + return @"Discovering"; + + case IDLE: + return @"Ready"; + + case SEND_NOTIFICATION_REQUEST: + case SEND_START_COMMAND: + case SEND_RECEIVE_COMMAND: + case SEND_FIRMWARE_DATA: + case WAIT_RECEIPT: + return @"Uploading"; + + case SEND_VALIDATE_COMMAND: + case SEND_RESET: + return @"Finishing"; + + case FINISHED: + return @"Finished"; + + case CANCELED: + return @"Canceled"; + + case ERROR: + return @"Error"; + } + return nil; +} + +-(unsigned long)binSize +{ + return self.firmwareData.length; +} + +- (void) setFirmwareURL:(NSURL *)firmwareURL +{ + NSString *extension = firmwareURL.pathExtension; + const char* str = [extension UTF8String]; + if(memcmp(str, "hex", 3) == 0) + { + NSLog(@"Select a hex file."); + NSData* hexData = [NSData dataWithContentsOfURL:firmwareURL]; + self.firmwareData = [IntelHex2BinConverter convert:hexData]; + self.appSize = hexData.length; + } + else if(memcmp(str, "bin", 3) == 0) + { + NSLog(@"Select a bin file."); + self.firmwareData = [NSData dataWithContentsOfURL:firmwareURL]; + self.appSize = self.firmwareData.length; + } + + self.appName = firmwareURL.path.lastPathComponent; + + NSLog(@"Set firmware with size %lu, notificationPacketInterval: %d", (unsigned long)self.firmwareData.length, self.notificationPacketInterval); +} + +- (void) setFirmwareBuffer:(NSData *)fwData +{ + self.firmwareData = fwData; + self.appName = @"Arduino upload"; + self.appSize = self.firmwareData.length; + + NSLog(@"Arduino uploaded"); + NSLog(@"Set firmware with size %lu, notificationPacketInterval: %d", (unsigned long)self.firmwareData.length, self.notificationPacketInterval); +} + +- (void) setProgress:(float)progress +{ + _progress = progress; + [self.delegate didUpdateProgress:progress]; +} + +/*! + * @brief Sends the next part of data packets. If data receipes has been switched OFF in the app settings this will try to send all packets in a single loop. + * Disabling data packet receipt procedure may fail as the packet queue on iDeveice has limited size and the transfer is much slower than this method + * adds new packets. The method stores the position of the last packet that has been sent itself and continues from that point when called again. + * If all data packets before receipt notification has been send a (void)didWriteDataPacket method is called. + * + * This method sets progress counter which causes [delegate didUpdateProgress:(float)progress] to be called. + */ +- (void) sendFirmwareChunk +{ + NSLog(@"sendFirmwareData"); + unsigned long currentDataSent = 0; + + for (int i = 0; (i < self.notificationPacketInterval || self.notificationPacketInterval == 0) && self.firmwareDataBytesSent < self.firmwareData.length; i++) + { + unsigned long length = (self.firmwareData.length - self.firmwareDataBytesSent) > DFUCONTROLLER_MAX_PACKET_SIZE ? DFUCONTROLLER_MAX_PACKET_SIZE : self.firmwareData.length - self.firmwareDataBytesSent; + + NSRange currentRange = NSMakeRange(self.firmwareDataBytesSent, length); + NSData *currentData = [self.firmwareData subdataWithRange:currentRange]; + + [self.target sendFirmwareData:currentData]; + + self.firmwareDataBytesSent += length; + self.progress = self.firmwareDataBytesSent / ((float) self.firmwareData.length); + currentDataSent += length; + } + + [self didWriteDataPacket]; + + NSLog(@"Sent %lu bytes, total %lu.", currentDataSent, self.firmwareDataBytesSent); +} + +- (void) didConnect +{ + NSLog(@"didConnect"); + if (self.state == INIT) + { + self.state = DISCOVERING; + [self.target startDiscovery]; + } +} + +- (void) didDisconnect:(NSError *) error +{ + NSLog(@"didDisconnect"); + + if (self.state != FINISHED && self.state != CANCELED && self.state != ERROR) + { + [self.delegate didDisconnect:error]; + } + self.state = INIT; +} + +- (void) didFinishDiscovery +{ + NSLog(@"didFinishDiscovery"); + if (self.state == DISCOVERING) + { + self.state = IDLE; + } +} + +- (void)didFinishDiscoveryWithError +{ + NSLog(@"didFinishDiscoveryWithError"); + if (self.state == DISCOVERING) + { + self.state = ERROR; + [self.delegate didErrorOccurred:DEVICE_NOT_SUPPORTED]; + } +} + +- (void) didReceiveResponse:(DFUTargetResponse) response forCommand:(DFUTargetOpcode) opcode +{ + NSLog(@"didReceiveResponse %d, forCommand %d, in state %d", response, opcode, self.state); + switch (self.state) + { + case SEND_START_COMMAND: + if (response == SUCCESS) + { + self.state = SEND_RECEIVE_COMMAND; + [self.target sendReceiveCommand]; + } + else + { + self.state = ERROR; + [self.delegate didErrorOccurred:response]; + [self.target sendResetAndActivate:NO]; + } + break; + + case SEND_VALIDATE_COMMAND: + if (response == SUCCESS) + { + self.state = SEND_RESET; + [self.target sendResetAndActivate:YES]; + } + else + { + self.state = ERROR; + [self.delegate didErrorOccurred:response]; + [self.target sendResetAndActivate:NO]; + } + break; + + case WAIT_RECEIPT: + if (response == SUCCESS && opcode == RECEIVE_FIRMWARE_IMAGE) + { + self.progress = 1.0f; + _uploadInterval = -[self.startDate timeIntervalSinceNow]; + self.state = SEND_VALIDATE_COMMAND; + [self.target sendValidateCommand]; + } + if (response != SUCCESS) + { + self.state = ERROR; + [self.delegate didErrorOccurred:response]; + [self.target sendResetAndActivate:NO]; + } + break; + + default: + break; + } +} + +- (void) didReceiveReceipt +{ + NSLog(@"didReceiveReceipt"); + + if (self.state == WAIT_RECEIPT) + { + self.state = SEND_FIRMWARE_DATA; + [self sendFirmwareChunk]; + } +} + +- (void) didWriteControlPoint +{ + NSLog(@"didWriteControlPoint, state %d", self.state); + + switch (self.state) + { + case SEND_NOTIFICATION_REQUEST: + self.state = SEND_START_COMMAND; + [self.target sendStartCommand:(int) self.firmwareData.length]; + break; + + case SEND_RECEIVE_COMMAND: + self.state = SEND_FIRMWARE_DATA; + self.startDate = [NSDate date]; + [self sendFirmwareChunk]; + break; + + case SEND_RESET: + self.state = FINISHED; + [self.delegate didFinishTransfer]; + break; + + case CANCELED: + [self.delegate didCancelTransfer]; + break; + + default: + break; + } +} + +- (void) didWriteDataPacket +{ + NSLog(@"didWriteDataPacket"); + + if (self.state == SEND_FIRMWARE_DATA) + { + self.state = WAIT_RECEIPT; + } +} + +- (void) startTransfer +{ + NSLog(@"startTransfer"); + + if (self.state == IDLE) + { + // Read number of packet before receipt notification from app settings + NSUserDefaults* settings = [NSUserDefaults standardUserDefaults]; + [settings synchronize]; + if ([settings boolForKey:@"dfu_notifications"]) + { + self.notificationPacketInterval = [settings integerForKey:@"dfu_number_of_packets"]; + } + else + { + NSLog(@"Set notification packet interval manually!"); + self.notificationPacketInterval = 10; + } + + NSLog(@"Notification packet interval: %d", self.notificationPacketInterval); + + NSLog(@"Wait 200 miliseconds before sending notification request..."); + usleep(200000); + + self.state = SEND_NOTIFICATION_REQUEST; + [self.target sendNotificationRequest:self.notificationPacketInterval]; + } +} + +- (void) pauseTransfer +{ + NSLog(@"pauseTransfer"); +} + +- (void) cancelTransfer +{ + NSLog(@"cancelTransfer"); + + if (self.state != INIT && self.state != CANCELED && self.state != FINISHED) + { + self.state = CANCELED; + [self.target sendResetAndActivate:NO]; + } +} + +@end diff --git a/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUTargetAdapter.h b/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUTargetAdapter.h new file mode 100644 index 0000000..fab4748 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUTargetAdapter.h @@ -0,0 +1,86 @@ +// +// TargetController.h +// nRF Loader +// +// Created by Ole Morten on 10/8/13. +// Copyright (c) 2013 Nordic Semiconductor. All rights reserved. +// + +#import +#import + +// BLE Device Service +#define DFU_SERVICE_UUID "00001530-1212-EFDE-1523-785FEABCD123" + +#define DFU_DATA_PACKET_UUID "00001532-1212-EFDE-1523-785FEABCD123" +#define DFU_DATA_PACKET_LEN 20 + +#define DFU_CONTROL_POINT_UUID "00001531-1212-EFDE-1523-785FEABCD123" +#define DFU_CONTROL_POINT_LEN 20 + +typedef enum +{ + START_DFU = 1, + INITIALIZE_DFU_PARAMS, + RECEIVE_FIRMWARE_IMAGE, + VALIDATE_FIRMWARE, + ACTIVATE_RESET, + RESET, + REPORT_SIZE, + REQUEST_RECEIPT, + RESPONSE_CODE = 0x10, + RECEIPT, +} DFUTargetOpcode; + +typedef enum +{ + SUCCESS = 0x01, + INVALID_STATE, + NOT_SUPPORTED, + DATA_SIZE_EXCEEDS_LIMIT, + CRC_ERROR, + OPERATION_FAILED, + DEVICE_NOT_SUPPORTED, +} DFUTargetResponse; + +@protocol DFUTargetAdapterDelegate +/*! + * @brief Called when service and characteristic discovery has finished. + */ +- (void) didFinishDiscovery; +/*! + * @brief Called when service and characteristic discovery has finished but the required service or characteristics were not found. + */ +- (void) didFinishDiscoveryWithError; +/*! + * @brief Invoked when Control Point characteristic has been written and confirmation has been received from peripheral. + */ +- (void) didWriteControlPoint; +/*! + * @brief Invoked when all data packets before notification were send. Number of data packets before notification receipt may be set in application settings. + */ +- (void) didWriteDataPacket; +/*! + * @brief Called when a response has been received from the peripheral. For data receipt see -(void)didReceiveReceipt method. + */ +- (void) didReceiveResponse:(DFUTargetResponse) response forCommand:(DFUTargetOpcode) opcode; +/*! + * @brief Called when a data receipt has been received. The peripheral is now ready for more data packets. + */ +- (void) didReceiveReceipt; +@end + +@interface DFUTargetAdapter : NSObject +@property (nonatomic) CBPeripheral *peripheral; + ++ (CBUUID *) serviceUUID; + +- (DFUTargetAdapter *) initWithDelegate:(id) delegate; +- (void) startDiscovery; +- (void) sendNotificationRequest:(uint16_t) interval; +- (void) sendStartCommand:(int) firmwareLength; +- (void) sendReceiveCommand; +- (void) sendFirmwareData:(NSData *) data; +- (void) sendValidateCommand; +- (void) sendResetAndActivate:(BOOL)activate; +@end diff --git a/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUTargetAdapter.m b/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUTargetAdapter.m new file mode 100644 index 0000000..d7f1f19 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/DFU/DFUTargetAdapter.m @@ -0,0 +1,232 @@ +// +// TargetController.m +// nRF Loader +// +// Created by Ole Morten on 10/8/13. +// Copyright (c) 2013 Nordic Semiconductor. All rights reserved. +// + +#import "DFUTargetAdapter.h" + +typedef struct __attribute__((packed)) +{ + uint8_t opcode; + union + { + uint16_t n_packets; + struct __attribute__((packed)) + { + uint8_t original; + uint8_t response; + }; + uint32_t n_bytes; + }; +} dfu_control_point_data_t; + +@interface DFUTargetAdapter () +@property CBCharacteristic *controlPointCharacteristic; +@property CBCharacteristic *packetCharacteristic; + +@property id delegate; +@end + +@implementation DFUTargetAdapter +@synthesize peripheral = _peripheral; +@synthesize controlPointCharacteristic = _controlPointCharacteristic; +@synthesize packetCharacteristic = _packetCharacteristic; + ++ (CBUUID *) serviceUUID +{ + return [CBUUID UUIDWithString:@DFU_SERVICE_UUID]; +} + ++ (CBUUID *) controlPointCharacteristicUUID +{ + return [CBUUID UUIDWithString:@DFU_CONTROL_POINT_UUID]; +} + ++ (CBUUID *) packetCharacteristicUUID +{ + return [CBUUID UUIDWithString:@DFU_DATA_PACKET_UUID]; +} + +- (DFUTargetAdapter *) initWithDelegate:(id)delegate +{ + if (self = [super init]) + { + _delegate = delegate; + } + return self; +} + +- (void) setPeripheral:(CBPeripheral *)peripheral +{ + NSLog(@"setPeripheral"); + _peripheral = peripheral; + _peripheral.delegate = self; +} + +- (void) startDiscovery +{ + NSLog(@"startDiscovery"); + [self.peripheral discoverServices:@[[self.class serviceUUID]]]; +} + +- (void) sendNotificationRequest:(uint16_t) interval +{ + NSLog(@"sendNotificationRequest"); + dfu_control_point_data_t data; + data.opcode = REQUEST_RECEIPT; + data.n_packets = interval; + + NSData *commandData = [NSData dataWithBytes:&data length:3]; + [self.peripheral writeValue:commandData forCharacteristic:self.controlPointCharacteristic type:CBCharacteristicWriteWithResponse]; +} + +- (void) sendStartCommand:(int) firmwareLength +{ + NSLog(@"sendStartCommand"); + dfu_control_point_data_t data; + data.opcode = START_DFU; + + NSData *commandData = [NSData dataWithBytes:&data length:1]; + [self.peripheral writeValue:commandData forCharacteristic:self.controlPointCharacteristic type:CBCharacteristicWriteWithResponse]; + + NSData *sizeData = [NSData dataWithBytes:&firmwareLength length:sizeof(firmwareLength)]; + [self.peripheral writeValue:sizeData forCharacteristic:self.packetCharacteristic type:CBCharacteristicWriteWithoutResponse]; +} + +- (void) sendReceiveCommand +{ + NSLog(@"sendReceiveCommand"); + dfu_control_point_data_t data; + data.opcode = RECEIVE_FIRMWARE_IMAGE; + + NSData *commandData = [NSData dataWithBytes:&data length:1]; + [self.peripheral writeValue:commandData forCharacteristic:self.controlPointCharacteristic type:CBCharacteristicWriteWithResponse]; +} + +- (void) sendFirmwareData:(NSData *) data +{ + [self.peripheral writeValue:data forCharacteristic:self.packetCharacteristic type:CBCharacteristicWriteWithoutResponse]; +} + +- (void) sendValidateCommand +{ + NSLog(@"sendValidateCommand"); + dfu_control_point_data_t data; + data.opcode = VALIDATE_FIRMWARE; + + NSData *commandData = [NSData dataWithBytes:&data length:1]; + [self.peripheral writeValue:commandData forCharacteristic:self.controlPointCharacteristic type:CBCharacteristicWriteWithResponse]; +} + +- (void) sendResetAndActivate:(BOOL)activate +{ + if (!self.controlPointCharacteristic) + { + return; + } + + NSLog(@"sendResetAndActivate %d", activate); + dfu_control_point_data_t data; + + if (activate) + { + data.opcode = ACTIVATE_RESET; + } + else + { + data.opcode = RESET; + } + + NSData *commandData = [NSData dataWithBytes:&data length:1]; + [self.peripheral writeValue:commandData forCharacteristic:self.controlPointCharacteristic type:CBCharacteristicWriteWithResponse]; +} + +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error +{ + if (error) + { + NSLog(@"didDiscoverServices failed: %@", error); + return; + } + + NSLog(@"didDiscoverServices succeeded."); + + for (CBService *s in peripheral.services) + { + if ([s.UUID isEqual:[self.class serviceUUID]]) + { + NSLog(@"Discover characteristics..."); + [self.peripheral discoverCharacteristics:@[[self.class controlPointCharacteristicUUID], [self.class packetCharacteristicUUID]] forService:s]; + return; + } + } + [self.delegate didFinishDiscoveryWithError]; +} + +- (void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error +{ + if (error) + { + NSLog(@"didDiscoverCharacteristics failed: %@", error); + return; + } + + NSLog(@"didDiscoverCharacteristics succeeded."); + + for (CBCharacteristic *c in service.characteristics) + { + if ([c.UUID isEqual:[self.class controlPointCharacteristicUUID]]) + { + NSLog(@"Found control point characteristic."); + self.controlPointCharacteristic = c; + + [self.peripheral setNotifyValue:YES forCharacteristic:self.controlPointCharacteristic]; + } + else if ([c.UUID isEqual:[self.class packetCharacteristicUUID]]) + { + NSLog(@"Found packet characteristic."); + self.packetCharacteristic = c; + } + } + + if (self.packetCharacteristic && self.controlPointCharacteristic) + { + [self.delegate didFinishDiscovery]; + } + else + { + [self.delegate didFinishDiscoveryWithError]; + } +} + +- (void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error +{ + + NSLog(@"Received notify %@. Value: %@.", characteristic, characteristic.value); + if ([characteristic.UUID isEqual:[self.class controlPointCharacteristicUUID]]) + { + dfu_control_point_data_t *packet = (dfu_control_point_data_t *) characteristic.value.bytes; + if (packet->opcode == RESPONSE_CODE) + { + NSLog(@"Response code"); + [self.delegate didReceiveResponse:packet->response forCommand:packet->original]; + } + if (packet->opcode == RECEIPT) + { + NSLog(@"RECEIPT"); + [self.delegate didReceiveReceipt]; + } + } +} + +- (void) peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error +{ + if (characteristic == self.controlPointCharacteristic) + { + [self.delegate didWriteControlPoint]; + } +} +@end diff --git a/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/PseudoTermController.h b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/PseudoTermController.h new file mode 100644 index 0000000..a4d3f02 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/PseudoTermController.h @@ -0,0 +1,56 @@ +// +// PseudoTermControoler.h +// SimpleControls +// +// Created by redbear on 14-8-13. +// Copyright (c) 2014年 RedBearLab. All rights reserved. +// + +#ifndef SimpleControls_PseudoTermControoler_h +#define SimpleControls_PseudoTermControoler_h + +#import +#include "com_iface.h" + +// Definitions for AVR901 protocol + +#define SOFTWARE_IDENTIFIER "CATERINA" + +/** Version major of the CDC bootloader. */ +#define BOOTLOADER_VERSION_MAJOR 0x01 +/** Version minor of the CDC bootloader. */ +#define BOOTLOADER_VERSION_MINOR 0x00 + +#define SPM_PAGESIZE (128) + +#define AVR_SIGNATURE_1 0x1E +#define AVR_SIGNATURE_2 0x95 +#define AVR_SIGNATURE_3 0x87 + +@protocol PseudoTermDelegate + +- (void) didOpenComport:(int) status; + +- (void) didCloseComport:(bool) status; + +- (void) didReceiveData:(NSData *) FirmwareData status:(bool) status; + +@end + +@interface PseudoTermController : NSObject +{ + bool status; + bool recDone; + NSData* FirmwareData; +} + +@property id delegate; + +- (PseudoTermController *) initWithDelegate:(id) delegate; +- (void) initPseudoTerm; +- (void) ParsePacket:(uint8_t *)rxBuf :(size_t)size; +- (void) closePseudoTerm:(bool) state; + +@end + +#endif diff --git a/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/PseudoTermController.m b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/PseudoTermController.m new file mode 100644 index 0000000..c17aa10 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/PseudoTermController.m @@ -0,0 +1,330 @@ +#import +#import "PseudoTermController.h" +//#import "NSFileManager.h" + +static com_iface_t *iface_a = NULL; +static PseudoTermController *PesudoTerm = nil; + +uint8_t Firmware[28 * 1024]; +uint32_t FirmwareSize = 0; +uint32_t CurrAddress = 0; + +static void receive_data(com_iface_t *iface, void *buf, size_t size); +static void connected(com_iface_t *iface, int connect); + +@implementation PseudoTermController +@synthesize delegate = _delegate; + +- (PseudoTermController *) initWithDelegate:(id) delegate +{ + if ((self = [super init]) != NULL) + { + _delegate = delegate; + status = NO; + recDone = NO; + PesudoTerm = self; + } + + return self; +} + +- (void) initPseudoTerm +{ + NSLog(@"Initiallising pseudo terminal......"); + + // Set up default callbackds for com ports + com_iface_set_default_receive_handler(receive_data); + com_iface_set_default_connect_handler(connected); + + com_iface_t **iface_p; + + // Work out which interface and settings we need to use. + iface_p = &iface_a; + + // Close port if open + if (*iface_p) + { + com_iface_close(*iface_p); + *iface_p = NULL; + } + + // Open port + if ( (*iface_p = com_iface_open() ) == NULL) + { + // Failed to open + [self.delegate didOpenComport: -1]; + + return; + } + + NSString *str; + str = [[NSString alloc] initWithUTF8String:iface_a->pterm.slave_name]; + NSLog(@"Pseudo: %@", str); + + NSFileManager *filemgr; + filemgr = [NSFileManager defaultManager]; + + if ([filemgr fileExistsAtPath: @"/tmp/tty.RBL-BLE" ] == YES) + { + NSLog(@"remove /tmp/tty.RBL-BLE"); + [filemgr removeItemAtPath: @"/tmp/tty.RBL-BLE" error: NULL]; + } + if ([filemgr createSymbolicLinkAtPath: @"/tmp/tty.RBL-BLE" withDestinationPath: str error: NULL] == YES) + { + NSLog (@"Link successful"); + [self.delegate didOpenComport: 0]; + } + else + { + NSLog (@"Link failed"); + [self.delegate didOpenComport: -2]; + } + + +} + +- (void) ParsePacket:(uint8_t *)rxBuf :(size_t)size +{ + printf("---------- Packet length %zd ---------- \r\n", size); + printf("Packet data: "); + for(uint8_t i=0; i> 8, SPM_PAGESIZE & 0xFF}; + com_iface_send(iface_a, buf, 3); + break; + } + // Read or Write firmware data + case 'g': + case 'B': + { + uint16_t BlockSize; + uint8_t MemoryType; + + BlockSize = rxBuf[1] << 8; + BlockSize |= rxBuf[2]; + MemoryType = rxBuf[3]; + + if ((MemoryType != 'E') && (MemoryType != 'F')) + { + /* Send error byte back to the host */ + uint8_t buf = '?'; + com_iface_send(iface_a, &buf, 1); + break; + } + + // Read firmware command + if(rxBuf[0] == 'g') + { + // Read flash + if(MemoryType == 'F') + { + printf("Read flash data, size: %d\r\n", BlockSize); + uint8_t buf[BlockSize]; + memcpy(buf, &Firmware[CurrAddress], BlockSize); + com_iface_send(iface_a, buf, BlockSize); + CurrAddress += BlockSize; + } + // Read eeprom + else if(rxBuf[3] == 'E') + { + printf("Read eeprom data, size: %d\r\n", BlockSize); + uint8_t buf[BlockSize]; + memset(buf, 0xFF, BlockSize); + com_iface_send(iface_a, buf, BlockSize); + } + } + // Write firmware command + else + { + // Write data to firmware rxBuf + if(MemoryType == 'F') + { + printf("Write flash data, size: %d\r\n", BlockSize); + memcpy(&Firmware[CurrAddress], &rxBuf[4], BlockSize); + FirmwareSize += BlockSize; + CurrAddress += BlockSize; + } + else + { + printf("Write eeprom data, size: %d\r\n", BlockSize); + } + + uint8_t buf = '\r'; + com_iface_send(iface_a, &buf, 1); + } + break; + } + default : + { + printf("Received unknown command\r\n"); + uint8_t buf = '?'; + com_iface_send(iface_a, &buf, 1); + break; + } + } + printf("------------------------------------- \r\n"); + printf("\r\n"); + + if(recDone) + { + if(YES == status) + { + FirmwareData = [[NSData alloc] initWithBytes:Firmware length:FirmwareSize]; + [self.delegate didReceiveData:FirmwareData status:YES]; + } + else + { + [self.delegate didReceiveData:nil status:NO]; + } + } +} + +- (void) closePseudoTerm:(bool) state +{ + NSLog(@"Closing pseudo terminal......"); + + com_iface_t **iface_p; + + // Work out which interface and settings we need to use. + iface_p = &iface_a; + + // Close port if open + if (*iface_p) + { + com_iface_close(*iface_p); + } + + recDone = NO; + status = NO; + + iface_a = NULL; + FirmwareSize = 0; + CurrAddress = 0; + + if(YES == state) + { + [self.delegate didCloseComport: YES]; + } + else + { + [self.delegate didCloseComport: NO]; + } +} + +@end + +static void receive_data(com_iface_t *iface, void *buf, size_t size) +{ + // Sanity check + if (!iface || !buf || (size <= 0)) + return; + + // Forward from Arduino + if ((iface == iface_a) || (iface->parent == iface_a)) + { + NSLog(@"Received data from Arduino"); + + // Read the data and parse it + [PesudoTerm ParsePacket:buf :size]; + } +} + +static void connected(com_iface_t *iface, int connect) +{ + if (!iface) + return; + NSLog(@"Connections: %d", connect); +} + diff --git a/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_error.c b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_error.c new file mode 100644 index 0000000..b7c4bbf --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_error.c @@ -0,0 +1,46 @@ +/* + * com_error.c + * + * Created by Martin Louis on 9/08/06. + * Copyright 2006 Romteck. All rights reserved. + * + */ + + +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +// Logs a connetion error. + +const char *com_iface_error_string(int resolve) +{ + switch (resolve ? h_errno : errno) + { + case HOST_NOT_FOUND: return "Host not found."; + case TRY_AGAIN: break; // Not considered an error + case NO_RECOVERY: return "Non-recoverable error."; + case NO_DATA: return "Host is up but does not have an address."; + case EBADF: + case ENOTSOCK: return "Bad socket descriptor."; + case EADDRNOTAVAIL: return "Address not available."; + case EAFNOSUPPORT: return "Address family not supported."; + case EISCONN: return "Socket already connected."; + case ETIMEDOUT: return "Connection timed out."; + case ECONNREFUSED: return "Connection refused."; + case ENETUNREACH: return "Network is unreachable."; + case EADDRINUSE: return "Address already in use."; + case EFAULT: return "Page fault in name parameter."; + case EINPROGRESS: + case EALREADY: break; // Should never happen since the socket is blocking + case EACCES: return "Destination is braodcast address."; + case EOPNOTSUPP: return "Operation not supported."; + case EWOULDBLOCK: return "Non-blocking socket would block."; + case EMFILE: return "Per-process descriptor table is full."; + case ENFILE: return "System file table is full."; + default: return "Undocumented error."; + } + + return ""; +} diff --git a/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_iface.c b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_iface.c new file mode 100644 index 0000000..629eaee --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_iface.c @@ -0,0 +1,239 @@ +/* + * com_iface.c + * + * Created by Martin Louis on 9/08/06. + * Copyright 2006 Martin Louis. All rights reserved. + * + */ + + +#include +#include +#include + +#include "com_iface.h" +#include "com_pterm.h" + + +///////////////////////////////////////////////////////////////// +// Configuration + +#define DEFAULT_SERIAL_BAUD_RATE 38400 // Baud rate used when none is specified on serial +#define DEFAULT_SERIAL_DATABITS 8 // Number of data bits used when none is specified on serial +#define DEFAULT_SERIAL_PARITY 'N' // Parity used when none is specified on serial +#define DEFAULT_SERIAL_STOPBITS 1 // Number of stop bits used when none is specified on serial +#define MAX_CONFIG_ARGS 8 + +#define LOCK_LIST pthread_mutex_lock(&list_mutex) +#define UNLOCK_LIST pthread_mutex_unlock(&list_mutex) +#define LOCK_CONN_LIST(x) pthread_mutex_lock(&(x)->sock_server.conn_list_mutex) +#define UNLOCK_CONN_LIST(x) pthread_mutex_unlock(&(x)->sock_server.conn_list_mutex) + + +///////////////////////////////////////////////////////////////// +// Public data +void (*com_iface_default_receive_handler)(com_iface_t *, void *, size_t) = NULL; +void (*com_iface_default_connect_handler)(com_iface_t *, int) = NULL; + +///////////////////////////////////////////////////////////////// +// Private data +static int initialised = 0; +static com_iface_t *first_iface = 0; +static com_iface_t *last_iface = 0; +static pthread_mutex_t list_mutex; // Mutex controls access to list + +// Initialise the com interfaces +static int initialise(void) +{ + // Initialise the list access mutex + initialised = (pthread_mutex_init(&list_mutex, NULL) == 0) ? 1 : 0; + + return initialised ? 0 : -1; +} + +// returns 1 if argument is a valid interface pointer, 0 if not +int com_iface_is_valid(com_iface_t *iface) +{ + com_iface_t *check_iface; + int is_valid = 0; + + if (!iface) + return 0; + + LOCK_LIST; + for (check_iface = first_iface; check_iface; check_iface = check_iface->next) + { + if (iface == check_iface) + { + is_valid = 1; + break; + } + } + UNLOCK_LIST; + + return is_valid; +} + +// Create a communications interface +com_iface_t *com_iface_open(void) +{ + com_iface_t *iface = NULL; + + // Initialise interfaces id not already done + if (!initialised) + { + if (initialise() != 0) + { + printf("Failed to initialise communications interfaces\r\n"); + return NULL; + } + } + + iface = com_iface_pterm_open(); + + return iface; +} + +// Sends data through an interface +// Returns number of characters sent. +int com_iface_send(com_iface_t *iface, void *buf, ssize_t size) +{ + // Sanity check + if (!initialised || !iface || !buf || (size <= 0)) + return 0; + + com_iface_pterm_send(iface, buf, size); + + return 0; +} + +// Tells a single interfaces thread to close the interface. +// Returns 0 if successful, -1 if not. +int com_iface_close(com_iface_t *iface) +{ + // Sanity check + if (!initialised || !iface) + return -1; + + com_iface_pterm_close(iface); + + // Not recognised + return -1; +} + +// Allocates a blank interface. +com_iface_t *com_iface_alloc(com_iface_t *parent) +{ + com_iface_t *iface; + + // Initialise interfaces id not already done + if (!initialised) + { + if (initialise() != 0) + { + printf("Failed to initialise communications interface\r\n"); + return NULL; + } + } + + // Allocate interface + if ((iface = (com_iface_t *)malloc(sizeof(com_iface_t))) == 0) + { + printf("Failed to allocate communications interface\r\n"); + return NULL; + } + + // Allocate RX buffer + if ((iface->rx_buf = (unsigned char *)malloc(sizeof(unsigned char) * COM_IFACE_RX_BUF_SIZE)) == 0) + { + free(iface); + printf("Failed to allocate communications interface.\n"); + return NULL; + } + + iface->name = NULL; + iface->parent = parent; + iface->close_request = 0; + iface->thread_running = 0; + iface->connections = 0; + iface->receive_handler = parent ? parent->receive_handler : com_iface_default_receive_handler; + iface->connection_handler = parent ? parent->connection_handler : com_iface_default_connect_handler; + + if (parent) + { + iface->tag = parent->tag; + iface->user_data = parent->user_data; + } + + // Add to list + LOCK_LIST; + iface->next = 0; + iface->prev = last_iface; + last_iface = iface; + if (iface->prev) + iface->prev->next = iface; + else + first_iface = iface; + UNLOCK_LIST; + + return iface; +} + +// Allocates a blank interface. +int com_iface_free(com_iface_t *iface) +{ + if (!com_iface_is_valid(iface)) + return -1; + + // Take interface from list + LOCK_LIST; + if (iface->prev) + iface->prev->next = iface->next; + else + first_iface = iface->next; + if (iface->next) + iface->next->prev = iface->prev; + else + last_iface = iface->prev; + + // release resources + if (iface->name) + free((void *)iface->name); + if (iface->rx_buf) + free(iface->rx_buf); + free(iface); + UNLOCK_LIST; + + // If the list is empty, destroy the mutex + LOCK_LIST; + if (first_iface == 0) + { + pthread_mutex_destroy(&list_mutex); + initialised = 0; + } + else + UNLOCK_LIST; + + // All done + return 0; +} + +// Sets a default receive handler that gets assigned to all newly opened ports. +void com_iface_set_default_receive_handler(void (*fnc)(com_iface_t *, void *, size_t)) +{ + com_iface_default_receive_handler = fnc; +} + +// Sets a default connect handler that gets assigned to all newly opened ports. +void com_iface_set_default_connect_handler(void (*fnc)(com_iface_t *, int)) +{ + com_iface_default_connect_handler = fnc; +} + +// Interface iteration functions (read only). +com_iface_t *com_iface_get_first(void) { return first_iface; } +com_iface_t *com_iface_get_last(void) { return last_iface; } +com_iface_t *com_iface_get_next(com_iface_t *iface) { return iface ? iface->next : NULL; } +void com_iface_lock(void) { LOCK_LIST; } +void com_iface_unlock(void) { UNLOCK_LIST; } + diff --git a/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_iface.h b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_iface.h new file mode 100644 index 0000000..9a767e9 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_iface.h @@ -0,0 +1,108 @@ +/* + * com.h + * + * Created by Martin Louis on 9/08/06. + * Copyright 2006 Martin Louis. All rights reserved. + * + * com_iface.c handles the interface to a communication channel. + * It opens the appropriate device and spawns a thread + * to read this device in the background. It passes received + * data to a function installed by the host application and + * accepts requests to send data. + */ + +#ifndef COM_H +#define COM_H + +#include +#include + +// When defined will spawn a new thread and iface for each new TCP connection. +// When undefed listen thread will select on all of the connections. +#undef COM_THREAD_PER_CONNECTION + +#define COM_IFACE_RX_BUF_SIZE 256 + +typedef enum +{ + comsigDTR, // Read / write + comsigDSR, // Read only + comsigRTS, // Read / write + comsigCTS, // Read only + comsigCD, // Read only + comsigRI // Read only +} com_sig_t; + + + +// Context for a com interface +typedef struct com_iface_s +{ + struct com_iface_s *next; // Link to next interface + struct com_iface_s *prev; // Link to previous interface + const char *name; // Name of port + struct com_iface_s *parent; // Link to parent if it is a connection spawned from a server + int close_request; // Is set to tell interface thread to close + int thread_running; // Flag indicates that a handler thread is running + int connections; // Number connections. Normally 1 but when iface is server, is num clients + unsigned char *rx_buf; // Receive buffer + void (*receive_handler)(struct com_iface_s *, void *, size_t); + void (*connection_handler)(struct com_iface_s *, int); + + // User fields. These are NEVER touched. + // Application can use this to track interfaces + // or associate custom data with them. + // EXCEPTION: When an asychronous TCP server + // accepts a connection and creates a new + // child port, its tag and user_data is + // copied from its parent. + int tag; + void *user_data; + + // Thread management + pthread_t thread; // Thread that controls the task + + // Interface specific data + union + { + // State data for pseudo terminals + struct + { + const char *slave_name; // Serial device + int fd; // File descriptor for reading and writing + } pterm; + }; + +} com_iface_t; + + +// Public data +void (*com_iface_default_receive_handler)(com_iface_t *, void *, size_t); +void (*com_iface_default_connect_handler)(com_iface_t *, int); + +// returns 1 if argument is a valid interface pointer, 0 if not +int com_iface_is_valid(com_iface_t *iface); + +// Interface open functions a communications interface +com_iface_t *com_iface_open(void); + +// Sends data through an interface +int com_iface_send(com_iface_t *iface, void *buf, ssize_t size); + +// Assigns default handler functions. These are assigned to all newly opened ports. +void com_iface_set_default_receive_handler(void (*fnc)(com_iface_t *, void *, size_t)); +void com_iface_set_default_connect_handler(void (*fnc)(com_iface_t *, int)); + +// Tells a single interfaces thread to close the interface. +// Returns 0 if successful, -1 if not. +int com_iface_close(com_iface_t *); + +// Interface iteration functions (read only). +com_iface_t *com_iface_get_first(void); +com_iface_t *com_iface_get_last(void); +com_iface_t *com_iface_get_next(com_iface_t *iface); +void com_iface_lock(void); +void com_iface_unlock(void); + + +#endif // COM_H diff --git a/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_pterm.c b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_pterm.c new file mode 100644 index 0000000..ad4c268 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_pterm.c @@ -0,0 +1,231 @@ +/* + * com_pterm.c + * + * Created by Martin Louis on 17/11/06. + * Copyright 2006 Martin Louis. All rights reserved. + * + */ + +#include "com_pterm.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#import +#include + +#include + +#import +#import + + +///////////////////////////////////////////////////////////////// +// Configuration +static void *receive_thread(void *thread_arg); + +///////////////////////////////////////////////////////////////// +// External functions +extern com_iface_t *com_iface_alloc(com_iface_t *parent); +extern void com_iface_free(com_iface_t *iface); + +///////////////////////////////////////////////////////////////// +// Creates a pseudo-terminal pair interface and spawns associated thread + +com_iface_t *com_iface_pterm_open(void) +{ + com_iface_t *iface; + char *slave_name; + + if ((iface = com_iface_alloc(NULL)) == NULL) + { + printf("Failed to allocate memory for pseudo terminal port.\r\n"); + return NULL; + } + + // Initialise + iface->pterm.slave_name = NULL; + iface->pterm.fd = -1; + + // Open device + if ((iface->pterm.fd = posix_openpt(O_RDWR | O_NOCTTY)) == -1) + { + printf("Unable to open master pseudo-terminal device.\r\n"); + com_iface_pterm_close(iface); + return NULL; + } + + // Get slave device + if ((slave_name = ptsname(iface->pterm.fd)) == NULL) + { + printf("Unable to get slave name for pseudo-terminal.\r\n"); + com_iface_pterm_close(iface); + return NULL; + } + + // Set the intrface name + asprintf((char **)&iface->name, "pseudo-term:%s", slave_name); + iface->pterm.slave_name = strdup(slave_name); + + // Change slave mode and owner + if (grantpt(iface->pterm.fd) != 0) + { + printf("Unable to set owner and mode on communications interface '%s'.\r\n", iface->name); + com_iface_pterm_close(iface); + return NULL; + } + + // Unlock slave + if (unlockpt(iface->pterm.fd) != 0) + { + printf("Unable to unlock on communications interface '%s'.\r\n", iface->name); + com_iface_pterm_close(iface); + return NULL; + } + + // Spawn handler thread + if (pthread_create(&iface->thread, NULL, receive_thread, iface) == 0) + { + iface->thread_running = 1; + } + else + { + printf("Unable to start communications interface '%s' (Thread failed).\r\n", iface->name); + com_iface_pterm_close(iface); + } + + return iface; +} + +///////////////////////////////////////////////////////////////// +// Closes a pseudo terminal interface and spawns associated thread + +int com_iface_pterm_close(com_iface_t *iface) +{ + // Sanity checks + if (!iface) + return -1; + + // If interface has an associated thread, ask it to close. + if (iface->thread_running) + { + // Ask thread to stop (will remove itself from interface list + iface->close_request = 1; + + // Wait for thread + pthread_join(iface->thread, NULL); + } + + // Restore original settings and close the device + if (iface->pterm.fd != -1) + { + close(iface->pterm.fd); + iface->pterm.fd = -1; + } + + // Release stuff from iface->pterm. + if (iface->pterm.slave_name) + free((void *)iface->pterm.slave_name); + iface->pterm.slave_name = NULL; + + //com_iface_free(iface);// Should free after thread exiting while loop + return 0; +} + + + +///////////////////////////////////////////////////////////////// +// Sends on a serial interface +ssize_t com_iface_pterm_send(com_iface_t *iface, void *buf, size_t size) +{ + ssize_t len; + + if (!iface || !buf || (size <= 0)) + return 0; + + if (iface->pterm.fd >= 0) + { + if ((len = write(iface->pterm.fd, buf, size)) < 0) + return 0; + return len; + } + + return 0; +} + + +//////////////////////////////////////////////////////////////////////////////// +// Receive thread +static void *receive_thread(void *thread_arg) +{ + com_iface_t *iface; + ssize_t len; + + iface = (com_iface_t *)thread_arg; + + // Make sure we have an interface + if (iface) + { + iface->connections++; + if (iface->connection_handler) + iface->connection_handler(iface, 1); + + // Keep reading stuff while we are + while (!iface->close_request) + { + fd_set fds; + struct timeval timeout; + int result; + + // Create a file descriptor set for accepting + // so we don't block indefinately + FD_ZERO(&fds); + FD_SET(iface->pterm.fd, &fds); + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + // Wait for data to be ready or timeout + result = select(iface->pterm.fd + 1, &fds, NULL, NULL, &timeout); + + // Check for timeout + if (result == 0) + continue; + + // Check for error + if (result < 0) + break; + + // Read a bunch of characters + len = read(iface->pterm.fd, iface->rx_buf, COM_IFACE_RX_BUF_SIZE); + if (len > 0) + { + // Send the received data to host application + if (iface->receive_handler) + iface->receive_handler(iface, iface->rx_buf, len); + } + } + + iface->connections--; + if (iface->connection_handler) + { + iface->connection_handler(iface, 0); + } + } + + iface->thread_running = 0; + com_iface_free(iface); + + printf("free pseudo terminal\r\n"); + + pthread_exit(0); +} + + + diff --git a/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_pterm.h b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_pterm.h new file mode 100644 index 0000000..bfc3bf5 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/PesoduTerm/com_pterm.h @@ -0,0 +1,24 @@ +// +// com_pterm.h +// SimpleControls +// +// Created by redbear on 14-8-17. +// Copyright (c) 2014年 RedBearLab. All rights reserved. +// + +#ifndef SimpleControls_com_pterm_h +#define SimpleControls_com_pterm_h + +#include +#include +#include +#include +#include +#include +#include "com_iface.h" + +com_iface_t *com_iface_pterm_open(void); +ssize_t com_iface_pterm_send(com_iface_t *iface, void *buf, size_t size); +int com_iface_pterm_close(com_iface_t *iface); + +#endif diff --git a/MacOSX/DFU_Mac/RBL_DFU/RBL_DFU-Info.plist b/MacOSX/DFU_Mac/RBL_DFU/RBL_DFU-Info.plist new file mode 100644 index 0000000..4eb83cc --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/RBL_DFU-Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + net.redbear.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSHumanReadableCopyright + Copyright © 2012 RedBearLab. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/MacOSX/DFU_Mac/RBL_DFU/RBL_DFU-Prefix.pch b/MacOSX/DFU_Mac/RBL_DFU/RBL_DFU-Prefix.pch new file mode 100644 index 0000000..ffbec8f --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/RBL_DFU-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'RBL_DFU' target in the 'RBL_DFU' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/MacOSX/DFU_Mac/RBL_DFU/en.lproj/Credits.rtf b/MacOSX/DFU_Mac/RBL_DFU/en.lproj/Credits.rtf new file mode 100644 index 0000000..896b1c0 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/en.lproj/Credits.rtf @@ -0,0 +1,29 @@ +{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw9840\paperh8400 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs24 \cf0 Engineering: +\b0 \ + Some people\ +\ + +\b Human Interface Design: +\b0 \ + Some other people\ +\ + +\b Testing: +\b0 \ + Hopefully not nobody\ +\ + +\b Documentation: +\b0 \ + Whoever\ +\ + +\b With special thanks to: +\b0 \ + Mom\ +} diff --git a/MacOSX/DFU_Mac/RBL_DFU/en.lproj/InfoPlist.strings b/MacOSX/DFU_Mac/RBL_DFU/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..0f167df --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/MacOSX/DFU_Mac/RBL_DFU/en.lproj/MainMenu.xib b/MacOSX/DFU_Mac/RBL_DFU/en.lproj/MainMenu.xib new file mode 100644 index 0000000..a45aedf --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/en.lproj/MainMenu.xib @@ -0,0 +1,728 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MacOSX/DFU_Mac/RBL_DFU/hex2bin/IntelHex2BinConverter.h b/MacOSX/DFU_Mac/RBL_DFU/hex2bin/IntelHex2BinConverter.h new file mode 100644 index 0000000..16b7d49 --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/hex2bin/IntelHex2BinConverter.h @@ -0,0 +1,18 @@ +// +// IntelHex2BinConverter.h +// nRF Toolbox +// +// Created by Aleksander Nowakowski on 15/01/14. +// Copyright (c) 2014 Nordic Semiconductor. All rights reserved. +// + +#import + +@interface IntelHex2BinConverter : NSObject + +/*! + * Converts the Intel HEX data to a bin format by subtracting only the data part from it. + Current implemetation does not support Extended Segment Addresses or Extended Linear Addresses. + */ ++ (NSData*)convert:(NSData*)hex; +@end diff --git a/MacOSX/DFU_Mac/RBL_DFU/hex2bin/IntelHex2BinConverter.m b/MacOSX/DFU_Mac/RBL_DFU/hex2bin/IntelHex2BinConverter.m new file mode 100644 index 0000000..841d34c --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/hex2bin/IntelHex2BinConverter.m @@ -0,0 +1,118 @@ +// +// IntelHex2BinConverter.m +// nRF Toolbox +// +// Created by Aleksander Nowakowski on 15/01/14. +// Copyright (c) 2014 Nordic Semiconductor. All rights reserved. +// + +#import "IntelHex2BinConverter.h" + +@implementation IntelHex2BinConverter + ++(const Byte)ascii2char:(const Byte*)ascii +{ + if (*ascii >= 'A') + return *ascii - 0x37; + + if (*ascii >= '0') + return *ascii - '0'; + return -1; +} + ++(const Byte)readByte:(const Byte*)pointer +{ + Byte first = [IntelHex2BinConverter ascii2char:pointer]; + Byte second = [IntelHex2BinConverter ascii2char:pointer + 1]; + + return (first << 4) | second; +} + ++(NSUInteger)calculateBinLength:(NSData*)hex +{ + if (hex == nil || hex.length == 0) + { + return 0; + } + + NSUInteger binLength = 0; + const NSUInteger hexLength = hex.length; + const Byte* pointer = (const Byte*)hex.bytes; + + do + { + const Byte semicollon = *pointer++; + + // Validate - each line of the file must have a semicollon as a firs char + if (semicollon != ':') + { + return 0; + } + + const UInt8 reclen = [IntelHex2BinConverter readByte:pointer]; pointer += 2; + pointer += 4; // Skip the offset + const UInt8 rectype = [IntelHex2BinConverter readByte:pointer]; pointer += 2; + + // If record type is Data Record (rectype = 0), add it's length + if (rectype == 0) + { + binLength += reclen; + } + + pointer += (reclen << 1); // Skip the data when calculating length + pointer += 2; // Skip the checksum + // Skip new line + if (*pointer == '\r') pointer++; + if (*pointer == '\n') pointer++; + } while (pointer != hex.bytes + hexLength); + + return binLength; +} + ++(NSData *)convert:(NSData *)hex +{ + const NSUInteger binLength = [IntelHex2BinConverter calculateBinLength:hex]; + const NSUInteger hexLength = hex.length; + const Byte* pointer = (const Byte*)hex.bytes; + + Byte* bytes = malloc(sizeof(Byte) * binLength); + Byte* output = bytes; + + do + { + const Byte semicollon = *pointer++; + + // Validate - each line of the file must have a semicollon as a firs char + if (semicollon != ':') + { + free(bytes); + return nil; + } + + const UInt8 reclen = [IntelHex2BinConverter readByte:pointer]; pointer += 2; + pointer += 4; // Skip the offset + const UInt8 rectype = [IntelHex2BinConverter readByte:pointer]; pointer += 2; + + // If record type is Data Record (rectype = 0), copy data to output buffer + if (rectype == 0) + { + for (int i = 0; i < reclen; i++) + { + *output++ = [IntelHex2BinConverter readByte:pointer]; pointer += 2; + } + } + else + { + pointer += (reclen << 1); // Skip the data when calculating length + } + + pointer += 2; // Skip the checksum + // Skip new line + if (*pointer == '\r') pointer++; + if (*pointer == '\n') pointer++; + } while (pointer != hex.bytes + hexLength); + + return [NSData dataWithBytesNoCopy:bytes length:binLength]; +} + +@end diff --git a/MacOSX/DFU_Mac/RBL_DFU/main.m b/MacOSX/DFU_Mac/RBL_DFU/main.m new file mode 100644 index 0000000..4769e3c --- /dev/null +++ b/MacOSX/DFU_Mac/RBL_DFU/main.m @@ -0,0 +1,14 @@ +// +// main.m +// SimpleControls +// +// Created by YC Poon on 27/10/12. +// Copyright (c) 2012 RedBearLab. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +} diff --git a/README.md b/README.md index fb30621..8f76e5f 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ Last updated: 2014/11/21 - **Jump2DFU:** It contains a sketch and the corresponding hex file that running on Blend / Blend Micro. The sketch demonstrates that when Blend / Blend Micro received a "DFU" string from central device, it will jump to the bootloader (no matter whether it is the DFU-OTA bootloader or the typical serial bootloader). +- **MacOSX:** It contais the source code of the RBL_DFU App on Mac OS X. + - **Release:** It contains the DFU-OTA bootloader we have generated for Blend / Blend Micro. - **Source:** It contains the source code and makefile to generate the DFU-OTA bootloader for Blend / Blend Micro.