支持泰凌微键盘
authorliangzhenying <867174124@qq.com>
Mon, 26 May 2025 09:29:16 +0000 (17:29 +0800)
committerliangzhenying <867174124@qq.com>
Mon, 26 May 2025 09:29:16 +0000 (17:29 +0800)
MouseSdk/AiMouseSdk/Keyboard/KeyboardHidManager.h
MouseSdk/AiMouseSdk/Keyboard/KeyboardHidManager.m
MouseSdk/AiMouseSdk/Manager/BleManager.m
MouseSdk/AiMouseSdk/Manager/DeviceManger.m
MouseSdk/AiMouseSdk/Manager/HidManager.m
MouseSdk/AiMouseSdk/Manager/HidManager_副本.m [new file with mode: 0644]
MouseSdk/AiMouseSdk/Manager/LogManager.m
MouseSdk/AiMouseSdk/Manager/TimerManager.m
MouseSdk/AiMouseSdk/TlwMouseSdk/TlwMouseSdk.m

index 7e5e0c1..743e99a 100644 (file)
@@ -1,31 +1,31 @@
+////
+////  KeyboardHidManager.h
+////  AiMouseManager
+////
+////  Created by incar on 2024/11/18.
+////
+//
+//#import <Foundation/Foundation.h>
+//#import "DeviceManger.h"
+//
+//NS_ASSUME_NONNULL_BEGIN
+//
+//@interface KeyboardHidManager : NSObject
+//@property (nonatomic, copy)void (^connectStateCallBack)(BOOL connected);/// 设备连接状态回调
+//@property (nonatomic, copy)void (^receiveInfoDataCallBack)(NSData *data);/// 设备信息数据回调
+//@property (nonatomic, copy)void (^logCallBack)(NSString *log);//输出日志
+//
+//@property (nonatomic, assign)AiMouseProductType productType;//
+//
+//+(KeyboardHidManager *)shared;
+//
+//- (void)open;
+//
+////- (void)close;
+//
+////写入数据
+//-(void)writeToDevice:(NSData *)data;
+//@end
+//
+//NS_ASSUME_NONNULL_END
 //
-//  KeyboardHidManager.h
-//  AiMouseManager
-//
-//  Created by incar on 2024/11/18.
-//
-
-#import <Foundation/Foundation.h>
-#import "DeviceManger.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface KeyboardHidManager : NSObject
-@property (nonatomic, copy)void (^connectStateCallBack)(BOOL connected);/// 设备连接状态回调
-@property (nonatomic, copy)void (^receiveInfoDataCallBack)(NSData *data);/// 设备信息数据回调
-@property (nonatomic, copy)void (^logCallBack)(NSString *log);//输出日志
-
-@property (nonatomic, assign)AiMouseProductType productType;//
-
-+(KeyboardHidManager *)shared;
-
-- (void)open;
-
-//- (void)close;
-
-//写入数据
--(void)writeToDevice:(NSData *)data;
-@end
-
-NS_ASSUME_NONNULL_END
-
index ae11b41..bfe4d93 100644 (file)
+////
+////  KeyboardHidManager.m
+////  AiMouseManager
+////
+////  Created by incar on 2024/11/18.
+////
 //
-//  KeyboardHidManager.m
-//  AiMouseManager
-//
-//  Created by incar on 2024/11/18.
-//
-
-#import "KeyboardHidManager.h"
-
-#include <IOKit/hid/IOHIDLib.h>
-#include <IOKit/hid/IOHIDKeys.h>
-#import <Security/Security.h>
-#import <Carbon/Carbon.h>
-#import <Cocoa/Cocoa.h>
-#import "AiDeviceAuthManager.h"
-
-@interface KeyboardHidManager ()
-@property(nonatomic, assign) IOHIDManagerRef hidManager;///hid管理
-@property(nonatomic, assign) IOHIDDeviceRef deviceInfoCha;//设备信息通道
-@end
-
-@implementation KeyboardHidManager
-+(KeyboardHidManager *)shared{
-    static KeyboardHidManager *manager = nil;
-    static dispatch_once_t oncePredicate;
-    dispatch_once(&oncePredicate, ^{
-        manager = [[KeyboardHidManager alloc]init];
-    });
-    return manager;
-}
-
-- (instancetype)init{
-    self = [super init];
-    if (self) {
-        
-    }
-    return self;
-}
-
-#pragma mark - Hid CallBack
-/// 匹配到设备回调
-static void hidAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) {
-    if ([DeviceManger shared].isConneted) {
-//        [[KeyboardHidManager shared] showLog:(@"当前处于连接状态,对监听到有USB 插入 的事件不做处理")];
-        return;
-    }
-//    1ea7  0064
-    uint32_t pid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey));
-    uint32_t vid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey));
-    uint32_t PrimaryUsagePage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsagePageKey));
-    uint32_t PrimaryUsage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsageKey));
-//    [[KeyboardHidManager shared] showLog:([NSString stringWithFormat:@"keyboard 发现设备%@,pid = %d,vid = %d ,page = %d, usage = %d",inIOHIDDeviceRef,pid,vid,PrimaryUsagePage,PrimaryUsage])];
-
-    
-    if((vid == 0x248a && pid == 0x6092)){
-        [[KeyboardHidManager shared] showLog:([NSString stringWithFormat:@"发现键盘%@,pid = %d,vid = %d ,page = %d, usage = %d",inIOHIDDeviceRef,pid,vid,PrimaryUsagePage,PrimaryUsage])];
-        [KeyboardHidManager shared].productType = AiMouseProductType_n;
-        [KeyboardHidManager shared].deviceInfoCha = inIOHIDDeviceRef;
-        //注册消息回调
-        unsigned char InputBuffer[64];
-        IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), &hidReceiveData, NULL);
-        
-        IOReturn result = IOHIDDeviceOpen([KeyboardHidManager shared].deviceInfoCha, kIOHIDOptionsTypeNone);
-        if (result != kIOReturnSuccess) {
-            [[KeyboardHidManager shared] showLog:[NSString stringWithFormat:@"打开设备失败! %d",result]];
-            [[AiDeviceAuthManager shared] showHidAlert];
-            return;
-        }else{
-            [[KeyboardHidManager shared] showLog:@"打开设备成功!"];
-            [KeyboardHidManager shared].connectStateCallBack(true) ;
-        }
-    }
- 
-}
-
-/// 设备移除回调
-static void hidDisAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) {
-    [[KeyboardHidManager shared] showLog:[NSString stringWithFormat:@"拔出设备 %@ ",inIOHIDDeviceRef]];
-    
-    if([KeyboardHidManager shared].deviceInfoCha){
-        [KeyboardHidManager shared].deviceInfoCha = nil;
-        [KeyboardHidManager shared].hidManager = nil;
-        [KeyboardHidManager shared].connectStateCallBack(false) ;
-    }
-}
-
-
-static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDReportType type, uint32_t reportID, uint8_t *report,CFIndex reportLength){
-    NSData *data = [[NSData alloc] initWithBytes:report length:reportLength];
-//    [[KeyboardHidManager shared] showLog:[NSString stringWithFormat:@"receive = %@",data]];
-    if([KeyboardHidManager shared].productType == AiMouseProductType_n){
-        uint32_t primaryUsagePage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsagePageKey));
-        uint32_t primaryUsage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsageKey));
-            NSData *data = [[NSData alloc] initWithBytes:report length:reportLength];
-            [KeyboardHidManager shared].receiveInfoDataCallBack(data);
-    }
-
-}
-
-#pragma mark - public
-- (void)open{
-    [self close];
-    //初始化
-    self.deviceInfoCha = nil;
-    self.hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
-    IOHIDManagerScheduleWithRunLoop(self.hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
-    IOReturn ret = IOHIDManagerOpen(self.hidManager, 0L);
-    if (ret != kIOReturnSuccess) {
-        [self showLog:(@"打开hid失败!")];
-    }else{
-//        [self showLog:(@"打开hid成功!")];
-    }
-    //设置匹配设备
-    //    ////供应商id
-    //    const long vendorID = 0x6675;
-    //    //产品id
-    //    const long productID = 0x8601;
-    //    //供应商id
-    //    const long vendorID = 0x10D6;
-    //    //产品id
-    //    const long productID = 0xB008;
-    NSMutableDictionary* dict= [NSMutableDictionary dictionary];
-    //    [dict setValue:[NSNumber numberWithLong:productID] forKey:[NSString stringWithCString:kIOHIDProductIDKey encoding:NSUTF8StringEncoding]];
-    //    [dict setValue:[NSNumber numberWithLong:vendorID] forKey:[NSString stringWithCString:kIOHIDVendorIDKey encoding:NSUTF8StringEncoding]];
-    IOHIDManagerSetDeviceMatching(self.hidManager, (__bridge CFMutableDictionaryRef)dict);
-    //设置匹配到设备回调
-    IOHIDManagerRegisterDeviceMatchingCallback(self.hidManager, &hidAppearDevice, NULL);
-    //设置移除设备回调
-    IOHIDManagerRegisterDeviceRemovalCallback(self.hidManager, &hidDisAppearDevice, NULL);
-}
-
-- (void)close{
-    if (self.hidManager == nil) {
-        return;
-    }
-//    [self showLog:@"关闭hid"];
-
-    IOReturn ret = IOHIDManagerClose(self.hidManager, 0);
-    self.hidManager = nil;
-    
-    if (ret != kIOReturnSuccess) {
-        [self showLog:(@"关闭hid失败!")];
-    }else{
-//        [self showLog:(@"关闭hid成功!")];
-        self.deviceInfoCha = nil;
-        self.hidManager = nil;
-    }
-}
-/// 发送数据给设备
--(void)writeToDevice:(NSData *)data{
-    if(self.deviceInfoCha == nil){
-        [self showLog:@"sendData: 请先连上设备"];
-        return;
-    }
-    
-    [self showLog:[NSString stringWithFormat:@"向usb设备发送数据 %@",data]];
-    IOReturn ret = IOHIDDeviceSetReport(self.deviceInfoCha, kIOHIDReportTypeOutput, 0, data.bytes, data.length);
-    if (ret != kIOReturnSuccess) {
-        [self showLog:[NSString stringWithFormat:@"发送失败! code = %d",ret]];
-    }else{
-//        [self showLog:@"发送成功!"];
-    }
-}
-
-
-- (void)showLog:(NSString *)log{
-    NSString *text =  [NSString stringWithFormat:@"[KeyboardHidManager] %@",log];
-    if(self.logCallBack) self.logCallBack(text);
-}
-
-/// 实际到数据长度
-static inline int get_data_len(uint8_t *buf, u_long len) {
-    if (len <= 0 ) return 0;
-    int url_len = 0;
-    while (buf[url_len] != 0x00) url_len++;
-    return url_len;
-}
-
-- (NSString *)dataToHexString:(NSData *)data {
-    NSUInteger length = data.length;
-    NSMutableString *result = [NSMutableString stringWithCapacity:length * 2];
-    const unsigned char *byte = data.bytes;
-    for (int i = 0; i < length; i++, byte++) {
-        [result appendFormat:@"%02X", *byte];
-    }
-    return result;
-}
-
-
-/// 获取对应属性值
-static uint32_t IOHIDDevGetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey) {
-    uint32_t outValue = 0;
-    if (inIOHIDDeviceRef != NULL) {
-        CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, inKey);
-        if (tCFTypeRef != NULL && (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef))  ) {
-            Boolean result = CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, &outValue);
-            if (!result) {
-                [[KeyboardHidManager shared] showLog:[NSString stringWithFormat:@"(HidManager)IOHIDDevGetUInt32Property:get %@ failed.", inKey]];
-            }
-        }
-    }
-    return outValue;
-}
-@end
+//#import "KeyboardHidManager.h"
+//
+//#include <IOKit/hid/IOHIDLib.h>
+//#include <IOKit/hid/IOHIDKeys.h>
+//#import <Security/Security.h>
+//#import <Carbon/Carbon.h>
+//#import <Cocoa/Cocoa.h>
+//#import "AiDeviceAuthManager.h"
+//
+//@interface KeyboardHidManager ()
+//@property(nonatomic, assign) IOHIDManagerRef hidManager;///hid管理
+//@property(nonatomic, assign) IOHIDDeviceRef deviceInfoCha;//设备信息通道
+//@end
+//
+//@implementation KeyboardHidManager
+//+(KeyboardHidManager *)shared{
+//    static KeyboardHidManager *manager = nil;
+//    static dispatch_once_t oncePredicate;
+//    dispatch_once(&oncePredicate, ^{
+//        manager = [[KeyboardHidManager alloc]init];
+//    });
+//    return manager;
+//}
+//
+//- (instancetype)init{
+//    self = [super init];
+//    if (self) {
+//        
+//    }
+//    return self;
+//}
+//
+//#pragma mark - Hid CallBack
+///// 匹配到设备回调
+//static void hidAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) {
+//    if ([DeviceManger shared].isConneted) {
+////        [[KeyboardHidManager shared] showLog:(@"当前处于连接状态,对监听到有USB 插入 的事件不做处理")];
+//        return;
+//    }
+////    1ea7  0064
+//    uint32_t pid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey));
+//    uint32_t vid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey));
+//    uint32_t PrimaryUsagePage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsagePageKey));
+//    uint32_t PrimaryUsage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsageKey));
+////    [[KeyboardHidManager shared] showLog:([NSString stringWithFormat:@"keyboard 发现设备%@,pid = %d,vid = %d ,page = %d, usage = %d",inIOHIDDeviceRef,pid,vid,PrimaryUsagePage,PrimaryUsage])];
+//
+//    
+//    if((vid == 0x248a && pid == 0x6092)){
+//        [[KeyboardHidManager shared] showLog:([NSString stringWithFormat:@"发现键盘%@,pid = %d,vid = %d ,page = %d, usage = %d",inIOHIDDeviceRef,pid,vid,PrimaryUsagePage,PrimaryUsage])];
+//        [KeyboardHidManager shared].productType = AiMouseProductType_n;
+//        [KeyboardHidManager shared].deviceInfoCha = inIOHIDDeviceRef;
+//        //注册消息回调
+//        unsigned char InputBuffer[64];
+//        IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), &hidReceiveData, NULL);
+//        
+//        IOReturn result = IOHIDDeviceOpen([KeyboardHidManager shared].deviceInfoCha, kIOHIDOptionsTypeNone);
+//        if (result != kIOReturnSuccess) {
+//            [[KeyboardHidManager shared] showLog:[NSString stringWithFormat:@"打开设备失败! %d",result]];
+//            [[AiDeviceAuthManager shared] showHidAlert];
+//            return;
+//        }else{
+//            [[KeyboardHidManager shared] showLog:@"打开设备成功!"];
+//            [KeyboardHidManager shared].connectStateCallBack(true) ;
+//        }
+//    }
+// 
+//}
+//
+///// 设备移除回调
+//static void hidDisAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) {
+//    [[KeyboardHidManager shared] showLog:[NSString stringWithFormat:@"拔出设备 %@ ",inIOHIDDeviceRef]];
+//    
+//    if([KeyboardHidManager shared].deviceInfoCha){
+//        [KeyboardHidManager shared].deviceInfoCha = nil;
+//        [KeyboardHidManager shared].hidManager = nil;
+//        [KeyboardHidManager shared].connectStateCallBack(false) ;
+//    }
+//}
+//
+//
+//static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDReportType type, uint32_t reportID, uint8_t *report,CFIndex reportLength){
+//    NSData *data = [[NSData alloc] initWithBytes:report length:reportLength];
+////    [[KeyboardHidManager shared] showLog:[NSString stringWithFormat:@"receive = %@",data]];
+//    if([KeyboardHidManager shared].productType == AiMouseProductType_n){
+//        uint32_t primaryUsagePage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsagePageKey));
+//        uint32_t primaryUsage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsageKey));
+//            NSData *data = [[NSData alloc] initWithBytes:report length:reportLength];
+//            [KeyboardHidManager shared].receiveInfoDataCallBack(data);
+//    }
+//
+//}
+//
+//#pragma mark - public
+//- (void)open{
+//    [self close];
+//    //初始化
+//    self.deviceInfoCha = nil;
+//    self.hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+//    IOHIDManagerScheduleWithRunLoop(self.hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+//    IOReturn ret = IOHIDManagerOpen(self.hidManager, 0L);
+//    if (ret != kIOReturnSuccess) {
+//        [self showLog:(@"打开hid失败!")];
+//    }else{
+////        [self showLog:(@"打开hid成功!")];
+//    }
+//    //设置匹配设备
+//    //    ////供应商id
+//    //    const long vendorID = 0x6675;
+//    //    //产品id
+//    //    const long productID = 0x8601;
+//    //    //供应商id
+//    //    const long vendorID = 0x10D6;
+//    //    //产品id
+//    //    const long productID = 0xB008;
+//    NSMutableDictionary* dict= [NSMutableDictionary dictionary];
+//    //    [dict setValue:[NSNumber numberWithLong:productID] forKey:[NSString stringWithCString:kIOHIDProductIDKey encoding:NSUTF8StringEncoding]];
+//    //    [dict setValue:[NSNumber numberWithLong:vendorID] forKey:[NSString stringWithCString:kIOHIDVendorIDKey encoding:NSUTF8StringEncoding]];
+//    IOHIDManagerSetDeviceMatching(self.hidManager, (__bridge CFMutableDictionaryRef)dict);
+//    //设置匹配到设备回调
+//    IOHIDManagerRegisterDeviceMatchingCallback(self.hidManager, &hidAppearDevice, NULL);
+//    //设置移除设备回调
+//    IOHIDManagerRegisterDeviceRemovalCallback(self.hidManager, &hidDisAppearDevice, NULL);
+//}
+//
+//- (void)close{
+//    if (self.hidManager == nil) {
+//        return;
+//    }
+////    [self showLog:@"关闭hid"];
+//
+//    IOReturn ret = IOHIDManagerClose(self.hidManager, 0);
+//    self.hidManager = nil;
+//    
+//    if (ret != kIOReturnSuccess) {
+//        [self showLog:(@"关闭hid失败!")];
+//    }else{
+////        [self showLog:(@"关闭hid成功!")];
+//        self.deviceInfoCha = nil;
+//        self.hidManager = nil;
+//    }
+//}
+///// 发送数据给设备
+//-(void)writeToDevice:(NSData *)data{
+//    if(self.deviceInfoCha == nil){
+//        [self showLog:@"sendData: 请先连上设备"];
+//        return;
+//    }
+//    
+//    [self showLog:[NSString stringWithFormat:@"向usb设备发送数据 %@",data]];
+//    IOReturn ret = IOHIDDeviceSetReport(self.deviceInfoCha, kIOHIDReportTypeOutput, 0, data.bytes, data.length);
+//    if (ret != kIOReturnSuccess) {
+//        [self showLog:[NSString stringWithFormat:@"发送失败! code = %d",ret]];
+//    }else{
+////        [self showLog:@"发送成功!"];
+//    }
+//}
+//
+//
+//- (void)showLog:(NSString *)log{
+//    NSString *text =  [NSString stringWithFormat:@"[KeyboardHidManager] %@",log];
+//    if(self.logCallBack) self.logCallBack(text);
+//}
+//
+///// 实际到数据长度
+//static inline int get_data_len(uint8_t *buf, u_long len) {
+//    if (len <= 0 ) return 0;
+//    int url_len = 0;
+//    while (buf[url_len] != 0x00) url_len++;
+//    return url_len;
+//}
+//
+//- (NSString *)dataToHexString:(NSData *)data {
+//    NSUInteger length = data.length;
+//    NSMutableString *result = [NSMutableString stringWithCapacity:length * 2];
+//    const unsigned char *byte = data.bytes;
+//    for (int i = 0; i < length; i++, byte++) {
+//        [result appendFormat:@"%02X", *byte];
+//    }
+//    return result;
+//}
+//
+//
+///// 获取对应属性值
+//static uint32_t IOHIDDevGetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey) {
+//    uint32_t outValue = 0;
+//    if (inIOHIDDeviceRef != NULL) {
+//        CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, inKey);
+//        if (tCFTypeRef != NULL && (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef))  ) {
+//            Boolean result = CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, &outValue);
+//            if (!result) {
+//                [[KeyboardHidManager shared] showLog:[NSString stringWithFormat:@"(HidManager)IOHIDDevGetUInt32Property:get %@ failed.", inKey]];
+//            }
+//        }
+//    }
+//    return outValue;
+//}
+//@end
index bbb8c6c..3b4cb75 100644 (file)
     [self performSelector:@selector(checkRightDevice) withObject:nil afterDelay:1];
 }
 - (void)showLog:(NSString *)log{
-    NSString *text =  [NSString stringWithFormat:@"[BleManager] %@",log];
+    NSString *text =  [NSString stringWithFormat:@"[Ble]%@",log];
     if(self.logCallBack) self.logCallBack(text);
 }
 
index 68ba5be..05dff21 100644 (file)
@@ -52,7 +52,7 @@
 - (instancetype)init{
     self = [super init];
     if (self) {
-        self.version = @"MouseSdk_v2025052401";
+        self.version = @"MouseSdk_v2025052601";
     }
     return self;
 }
@@ -97,7 +97,8 @@
 //            [self.hid close];
         }
         else{
-//            [self.ble open];
+
+            [self.ble open];
             if (self.retryTimes < 5) {
                 [self.hid open];
             }
index 76ebd50..48f951a 100644 (file)
@@ -50,7 +50,7 @@ static void hidAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOH
     uint32_t vid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey));
     uint32_t page = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsagePageKey));
     uint32_t usage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsageKey));
-    [[HidManager shared] showLog: [NSString stringWithFormat:@"发现设备 %@",inIOHIDDeviceRef]];
+//    [[HidManager shared] showLog: [NSString stringWithFormat:@"发现设备 %@",inIOHIDDeviceRef]];
    if(vid == 3468 && pid == 786){
        if (page == 65282 && usage == 2) {
            [HidManager shared].productType = AiMouseProductType_m8;
diff --git a/MouseSdk/AiMouseSdk/Manager/HidManager_副本.m b/MouseSdk/AiMouseSdk/Manager/HidManager_副本.m
new file mode 100644 (file)
index 0000000..f72a35c
--- /dev/null
@@ -0,0 +1,379 @@
+//
+//  HidManager.m
+//  MouseSdk
+//
+//  Created by incar on 2024/3/26.
+//
+
+#import "HidManager.h"
+#include <IOKit/hid/IOHIDLib.h>
+#include <IOKit/hid/IOHIDKeys.h>
+#import <Security/Security.h>
+#import <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+#import "AiDeviceAuthManager.h"
+#import "TlwTools.h"
+#import "Tlw2ReceiveManager.h"
+@interface HidManager ()
+@property(nonatomic, assign) IOHIDManagerRef hidManager;///hid管理
+@property(nonatomic, assign) IOHIDDeviceRef deviceInfoCha;//设备信息通道
+@property(nonatomic, assign) IOHIDDeviceRef voiceCha;//语音通道
+@property(nonatomic, strong) Tlw2ReceiveManager *tlw2Receiver;
+@end
+
+@implementation HidManager
++(HidManager *)shared{
+    static HidManager *manager = nil;
+    static dispatch_once_t oncePredicate;
+    dispatch_once(&oncePredicate, ^{
+        manager = [[HidManager alloc]init];
+    });
+    return manager;
+}
+
+- (instancetype)init{
+    self = [super init];
+    if (self) {
+        
+    }
+    return self;
+}
+
+#pragma mark - Hid CallBack
+/// 匹配到设备回调
+static void hidAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) {
+    [[HidManager shared] showLog: [NSString stringWithFormat:@"发现设备 %@",inIOHIDDeviceRef]];
+    if ([DeviceManger shared].isConneted) {
+//        [[HidManager shared] showLog:(@"当前处于连接状态,对监听到有USB 插入 的事件不做处理")];
+        return;
+    }
+    uint32_t pid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey));
+    uint32_t vid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey));
+    uint32_t page = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsagePageKey));
+    uint32_t usage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsageKey));
+    
+   if(vid == 3468 && pid == 786){
+       if (page == 65282 && usage == 2) {
+           [HidManager shared].productType = AiMouseProductType_m8;
+           [HidManager shared].deviceInfoCha = inIOHIDDeviceRef;
+           unsigned char InputBuffer[64];
+           IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), &hidReceiveData, NULL);
+           
+           IOReturn result = IOHIDDeviceOpen(inIOHIDDeviceRef, kIOHIDOptionsTypeNone);
+           if (result != kIOReturnSuccess) {
+               [[HidManager shared] showLog:[NSString stringWithFormat:@"打开设备失败! %d",result]];
+               [[AiDeviceAuthManager shared] showHidAlert];
+               return;
+           }else{
+               [[HidManager shared] showLog:@"打开设备成功!"];
+               [HidManager shared].connectStateCallBack(true) ;
+           }
+       }
+//       else if (page == 1 && usage == 2){
+//           [HidManager shared].productType = AiMouseProductType_m8;
+//           [HidManager shared].deviceInfoCha = inIOHIDDeviceRef;
+//           unsigned char InputBuffer[64];
+//           IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), &hidReceiveData, NULL);
+//           
+//           IOReturn result = IOHIDDeviceOpen(inIOHIDDeviceRef, kIOHIDOptionsTypeNone);
+//           if (result != kIOReturnSuccess) {
+//               [[HidManager shared] showLog:[NSString stringWithFormat:@"打开设备失败! %d",result]];
+//               [[AiDeviceAuthManager shared] showHidAlert];
+//               return;
+//           }else{
+//               [[HidManager shared] showLog:@"打开设备成功!"];
+//               //            [HidManager shared].connectStateCallBack(true) ;
+//           }
+//       }
+       return;
+    }
+    if((vid == 0x248a && pid == 0x6092)){
+        [HidManager shared].productType = AiMouseProductType_keyboard;
+        [HidManager shared].deviceInfoCha = inIOHIDDeviceRef;
+        unsigned char InputBuffer[64];
+        IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), &hidReceiveData, NULL);
+        
+        IOReturn result = IOHIDDeviceOpen([HidManager shared].deviceInfoCha, kIOHIDOptionsTypeNone);
+        if (result != kIOReturnSuccess) {
+            [[HidManager shared] showLog:[NSString stringWithFormat:@"打开设备失败! %d",result]];
+            [[AiDeviceAuthManager shared] showHidAlert];
+            return;
+        }else{
+            [[HidManager shared] showLog:@"打开设备成功!"];
+            [HidManager shared].connectStateCallBack(true) ;
+        }
+        return;
+    }
+    else if((vid == 0x1ea7 && pid == 0x0064)
+            || (vid == 0x1ea7 && pid == 0x0066)
+            || (vid == 0x32c2 && pid == 0x0066)
+            ){
+        [HidManager shared].productType = AiMouseProductType_n;
+        [HidManager shared].deviceInfoCha = inIOHIDDeviceRef;
+        unsigned char InputBuffer[64];
+        IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), &hidReceiveData, NULL);
+        
+        IOReturn result = IOHIDDeviceOpen([HidManager shared].deviceInfoCha, kIOHIDOptionsTypeNone);
+        if (result != kIOReturnSuccess) {
+            [[HidManager shared] showLog:[NSString stringWithFormat:@"打开设备失败! %d",result]];
+            [[AiDeviceAuthManager shared] showHidAlert];
+            return;
+        }else{
+            [[HidManager shared] showLog:@"打开设备成功!"];
+            [HidManager shared].connectStateCallBack(true) ;
+        }
+    }
+    else if(vid == 0x10D6 && pid == 0xB008){
+        [HidManager shared].productType = AiMouseProductType_tlw;
+        [HidManager shared].deviceInfoCha = inIOHIDDeviceRef;
+        unsigned char InputBuffer[64];
+        IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), &hidReceiveData, NULL);
+        
+        IOReturn result = IOHIDDeviceOpen([HidManager shared].deviceInfoCha, kIOHIDOptionsTypeNone);
+        if (result != kIOReturnSuccess) {
+            [[HidManager shared] showLog:[NSString stringWithFormat:@"打开设备失败! %d",result]];
+            [[AiDeviceAuthManager shared] showHidAlert];
+            return;
+        }else{
+            [[HidManager shared] showLog:@"打开设备成功!"];
+            [HidManager shared].connectStateCallBack(true) ;
+        }
+    }
+    else  if(vid == 0x6675 && pid == 0x8601){
+        [HidManager shared].productType = AiMouseProductType_frk;
+        AiMouse.shared.tlw2 = false;
+        if(page == 1 && usage == 0){
+            unsigned char InputBuffer[128];
+            IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), hidReceiveData, NULL);
+            IOReturn result = IOHIDDeviceOpen(inIOHIDDeviceRef, kIOHIDOptionsTypeNone);
+            if (result != kIOReturnSuccess) {
+                [[HidManager shared] showLog:[NSString stringWithFormat:@"frk打开设备信息失败! %d",result]];
+                [[AiDeviceAuthManager shared] showHidAlert];
+                return;
+            }else{
+                [HidManager shared].deviceInfoCha = inIOHIDDeviceRef;
+                
+                [[HidManager shared] showLog:@"frk打开设备信息成功!"];
+                if([HidManager shared].voiceCha != nil){
+                    [HidManager shared].connectStateCallBack(true);
+                }
+            }
+        }
+        else if(page == 65283 && usage == 0){
+            unsigned char InputBuffer[128];
+            IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), hidReceiveData, NULL);
+            
+            IOReturn result = IOHIDDeviceOpen(inIOHIDDeviceRef, kIOHIDOptionsTypeNone);
+            if (result != kIOReturnSuccess) {
+                [[HidManager shared] showLog:[NSString stringWithFormat:@"frk打开设备voice失败! %d",result]];
+                [[AiDeviceAuthManager shared] showHidAlert];
+                return;
+            }else{
+                [HidManager shared].voiceCha = inIOHIDDeviceRef;
+                
+                [[HidManager shared] showLog:@"frk打开设备voice成功!"];
+                if([HidManager shared].deviceInfoCha != nil){
+                    [HidManager shared].connectStateCallBack(true);
+                }
+            }
+        }
+    }
+    else  if(vid == 0x6675 && pid == 0x8602){
+        [HidManager shared].productType = AiMouseProductType_frk;
+        AiMouse.shared.tlw2 = true;
+        [HidManager shared].tlw2Receiver = [[Tlw2ReceiveManager alloc] init];
+            if(page == 65519 && usage == 0){
+            unsigned char InputBuffer[128];
+            IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), hidReceiveData, NULL);
+            
+            IOReturn result = IOHIDDeviceOpen(inIOHIDDeviceRef, kIOHIDOptionsTypeNone);
+            if (result != kIOReturnSuccess) {
+                [[HidManager shared] showLog:[NSString stringWithFormat:@"tlw2打开设备voice失败! %d",result]];
+                [[AiDeviceAuthManager shared] showHidAlert];
+                return;
+            }else{
+                [HidManager shared].deviceInfoCha = inIOHIDDeviceRef;
+                
+                [[HidManager shared] showLog:@"tlw2打开设备voice成功!"];
+                if([HidManager shared].deviceInfoCha != nil){
+                    [HidManager shared].connectStateCallBack(true);
+                }
+            }
+        }
+    }
+}
+
+/// 设备移除回调
+static void hidDisAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) {
+    [[HidManager shared] showLog:[NSString stringWithFormat:@"拔出设备 %@ ",inIOHIDDeviceRef]];
+    if([HidManager shared].deviceInfoCha == inIOHIDDeviceRef){
+        [HidManager shared].deviceInfoCha = nil;
+        [HidManager shared].voiceCha = nil;
+//        [HidManager shared].hidManager = nil;
+        [HidManager shared].connectStateCallBack(false) ;
+    }
+}
+
+static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDReportType type, uint32_t reportID, uint8_t *report,CFIndex reportLength){
+    NSData *data = [[NSData alloc] initWithBytes:report length:reportLength];
+        if (data.length <= 4) {
+            return;
+        }
+//    [[HidManager shared] showLog:[NSString stringWithFormat:@"[reciv] %@",data]];
+    //    return;
+    if([HidManager shared].productType == AiMouseProductType_keyboard){
+        NSData *data = [[NSData alloc] initWithBytes:report length:reportLength];
+        [HidManager shared].receiveInfoDataCallBack(data);
+    }
+    else if([HidManager shared].productType == AiMouseProductType_n){
+        NSData *data = [[NSData alloc] initWithBytes:report length:reportLength];
+        [HidManager shared].receiveInfoDataCallBack(data);
+    }
+    else if([HidManager shared].productType == AiMouseProductType_tlw){
+        if (report[0] == 0x01 || report[0] == 0x02) {
+            //鼠标键盘活动事件
+            return;
+        }
+        uint32_t page = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsagePageKey));
+        uint32_t usage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsageKey));
+//        [[HidManager shared] showLog:[NSString stringWithFormat:@"[reciv]page = %d,usage = %d, %@",page,usage,data]];
+        if(page == 1 && usage == 2){
+            NSData *data = [[NSData alloc] initWithBytes:report length:reportLength];
+            [HidManager shared].receiveInfoDataCallBack(data);
+        }
+    }
+    else if([HidManager shared].productType == AiMouseProductType_frk){
+        
+        NSInteger len = get_data_len(report, (int)reportLength);
+        NSData *data = [[NSData alloc] initWithBytes:report length:len];
+        uint32_t page = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsagePageKey));
+        uint32_t usage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsageKey));
+        [[HidManager shared] showLog:[NSString stringWithFormat:@"[reciv]%@",[TlwTools dataToHexString:data]]];
+        if(page == 1 && usage == 0){
+            [[AiMouse shared] sendDeviceDataToSdk:data];
+        }
+        else if(page == 65283 && usage == 0){
+            [[AiMouse shared] sendAiDataToSdk:data];
+        }
+        else if(page == 65519 && usage == 0){
+            //泰凌微2代
+            [[HidManager shared].tlw2Receiver receive:data];
+        }
+    }
+}
+
+#pragma mark - public
+- (BOOL)close{
+    if (self.hidManager != nil) {
+        if (self.deviceInfoCha != nil) {
+            // 取消所有报告回调
+            IOHIDDeviceRegisterInputReportCallback(self.deviceInfoCha, NULL, 0, NULL, NULL);
+            IOReturn ret = IOHIDDeviceClose(self.deviceInfoCha, kIOHIDOptionsTypeNone);
+            if (ret != kIOReturnSuccess) {
+                [self showLog:(@"关闭info IOHIDManagerRef失败!")];
+                return false;
+            }
+        }
+        if (self.voiceCha != nil) {
+            IOHIDDeviceRegisterInputReportCallback(self.voiceCha, NULL, 0, NULL, NULL);
+            IOReturn ret = IOHIDDeviceClose(self.voiceCha, kIOHIDOptionsTypeNone);
+            if (ret != kIOReturnSuccess) {
+                [self showLog:(@"关闭voice IOHIDManagerRef失败!")];
+                return false;
+            }
+        }
+        
+        IOReturn ret = IOHIDManagerClose(self.hidManager, 0);
+        if (ret != kIOReturnSuccess) {
+            [self showLog:(@"关闭hid失败!")];
+            return false;
+        }
+        
+        self.deviceInfoCha = nil;
+        self.voiceCha = nil;
+        self.hidManager = nil;
+    }
+    return true;
+}
+- (void)open{
+//    if ([self close] == false) {
+//        return;
+//    }
+    [self close];
+    self.hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+    IOHIDManagerScheduleWithRunLoop(self.hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+    IOReturn ret = IOHIDManagerOpen(self.hidManager, 0L);
+    if (ret != kIOReturnSuccess) {
+        [self showLog:(@"打开hid失败!")];
+    }else{
+        [self showLog:(@"打开hid成功!")];
+    }
+    //设置匹配设备
+    NSMutableDictionary* dict= [NSMutableDictionary dictionary];
+    //    [dict setValue:[NSNumber numberWithLong:productID] forKey:[NSString stringWithCString:kIOHIDProductIDKey encoding:NSUTF8StringEncoding]];
+    //    [dict setValue:[NSNumber numberWithLong:vendorID] forKey:[NSString stringWithCString:kIOHIDVendorIDKey encoding:NSUTF8StringEncoding]];
+    IOHIDManagerSetDeviceMatching(self.hidManager, (__bridge CFMutableDictionaryRef)dict);
+    //设置匹配到设备回调
+    IOHIDManagerRegisterDeviceMatchingCallback(self.hidManager, &hidAppearDevice, NULL);
+    //设置移除设备回调
+    IOHIDManagerRegisterDeviceRemovalCallback(self.hidManager, &hidDisAppearDevice, NULL);
+}
+
+/// 发送数据给设备
+-(void)writeToDevice:(NSData *)data{
+    if(self.deviceInfoCha == nil){
+        [self showLog:@"sendData: 请先连上设备"];
+        return;
+    }
+//    data = [self addFullData:data];
+    [self showLog:[NSString stringWithFormat:@"[send] %@ %@",self.deviceInfoCha,data]];
+    IOReturn ret = IOHIDDeviceSetReport(self.deviceInfoCha, kIOHIDReportTypeOutput, 0x05, data.bytes, data.length);
+    if (ret != kIOReturnSuccess) {
+        [self showLog:[NSString stringWithFormat:@"发送失败! code = %d",ret]];
+    }else{
+        //        [self showLog:@"发送成功!"];
+    }
+}
+
+- (NSData *)addFullData:(NSData *)data{
+    NSMutableData *fullData = [[NSMutableData alloc] initWithData:data];
+    if (fullData.length < 64) {
+        NSInteger len = 64 - fullData.length;
+        for (NSInteger i = 0; i < len; i++) {
+            uint8_t d = 0x00;
+            [fullData  appendBytes:&d length:1];
+        }
+    }
+    return fullData;
+}
+
+- (void)showLog:(NSString *)log{
+    NSString *text =  [NSString stringWithFormat:@"[HidManager]%@",log];
+    if(self.logCallBack) self.logCallBack(text);
+}
+
+/// 实际到数据长度
+static inline int get_data_len(uint8_t *buf, int len) {
+    if (len <= 0 ) return 0;
+    int end = len - 1;
+    while (end >= 0 && (buf[end] == 0 || buf[end - 1] == 0)) {
+        end--;
+    }
+    return end + 1;
+}
+
+/// 获取对应属性值
+static uint32_t IOHIDDevGetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey) {
+    uint32_t outValue = 0;
+    if (inIOHIDDeviceRef != NULL) {
+        CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, inKey);
+        if (tCFTypeRef != NULL && (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef))  ) {
+            Boolean result = CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, &outValue);
+            if (!result) {
+                [[HidManager shared] showLog:[NSString stringWithFormat:@"IOHIDDevGetUInt32Property:get %@ failed.", inKey]];
+            }
+        }
+    }
+    return outValue;
+}
+@end
index 652fdfe..0ba90fa 100644 (file)
@@ -85,7 +85,7 @@
         
         NSString *text1 = [[LogManager shared] dateString];
         NSString *text2 = [logs componentsJoinedByString:@" "];
-        NSString *logString = [NSString stringWithFormat:@"%@ ~ [LogManager]%@",text1,text2];
+        NSString *logString = [NSString stringWithFormat:@"%@ ~ %@",text1,text2];
         NSLog(@"%@",logString);
         
         if ([LogManager shared].debugLevel == 2) {
index 556807b..8895d2a 100644 (file)
@@ -32,7 +32,7 @@
 //        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
 //        [[NSRunLoop currentRunLoop] run];
 //    });
-    self.timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:true];
+    self.timer = [NSTimer scheduledTimerWithTimeInterval:8 target:self selector:@selector(timerAction) userInfo:nil repeats:true];
 }
 
 - (void)timerAction{
index a940f0c..5259e61 100644 (file)
@@ -10,6 +10,7 @@
 #import "TlwTools.h"
 #import "AiRecordManager.h"
 
+
 @implementation TlwDeviceInfo
 -(NSString *)description{
     NSString *info = [NSString stringWithFormat:@"version = %@ DPI = %d batteryState = %d batteryValue = %d",self.version,self.DPI,self.batteryState,self.batteryValue];
@@ -43,6 +44,7 @@
 @property (nonatomic,strong)void (^getFullInfoCallBack)(AiMouseDeviceInfo *info,NSError *error);
 @property (nonatomic,strong)AiMouseDeviceInfo *fullInfo;
 @property (nonatomic,assign)NSInteger questTimes;
+@property (nonatomic, strong) NSTimer *timer;
 @end
 
 @implementation TlwMouse
@@ -62,7 +64,7 @@
         _recordManager = [[AiRecordManager alloc] init];
         __weak typeof(self) ws = self;
         _recordManager.didRecordData = ^(NSData * _Nonnull data) {
-            [ws showLog:[NSString stringWithFormat:@"%@",data]];
+            [ws showLog:[NSString stringWithFormat:@"[audio]%@",data]];
             [ws sendRecordData:data];
         };
     }
     }
 }
 - (void)getDeviceInfo:(void (^)(TlwDeviceInfo *deviceInfo,NSError *error))finished{
+    [self addSendTimer];
     if(self.connectType == AiMouseConnectType_hid){
         self.getMouseInfoCallBack = finished;
         //        0x05fff1fec09f0114ef
 - (void)getFullDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))finished{
     self.getFullInfoCallBack = finished;
     __weak typeof(self) ws = self;
-    [self getDeviceInfo:^(TlwDeviceInfo *deviceInfo, NSError *error) {
-        if(deviceInfo != nil){
-            NSDictionary *dict = @{
-                @"1200":@"1",
-                @"1600":@"2",
-                @"2400":@"3",
-                @"4800":@"4",
-            };
-            
-            NSString *CPI_list = [[dict allKeys] componentsJoinedByString:@","];
-            NSString *level = [NSString stringWithFormat:@"%d",deviceInfo.DPI];
-            NSString *dpiValue = @"1200";
-            
-            for (NSString *key in dict) {
-                if ([dict[key] isEqualToString:level]) {
-                    dpiValue = key;
-                    break;;
-                }
-            }
-            
-            AiMouseDeviceInfo *info = [[AiMouseDeviceInfo alloc] init];
-            info.type = 0;
-            info.battery_power = [NSString stringWithFormat:@"%d",deviceInfo.batteryValue] ;
-            info.version = [NSString stringWithFormat:@"%@",deviceInfo.version];
-            info.CPI_list = CPI_list;
-            info.CPI = dpiValue;
-            ws.fullInfo = info;
-            
-            [ws getSnInfo:^(TlwSnInfo *snInfo, NSError *error) {
-                if( info != nil){
+    [ws getSnInfo:^(TlwSnInfo *snInfo, NSError *error) {
+        if( snInfo != nil){
+            [self getDeviceInfo:^(TlwDeviceInfo *deviceInfo, NSError *error) {
+                    NSDictionary *dict = @{
+                        @"1200":@"1",
+                        @"1600":@"2",
+                        @"2400":@"3",
+                        @"4800":@"4",
+                    };
+                    
+                    NSString *CPI_list = [[dict allKeys] componentsJoinedByString:@","];
+                    NSString *level = [NSString stringWithFormat:@"%d",deviceInfo.DPI];
+                    NSString *dpiValue = @"1200";
+                    
+                    for (NSString *key in dict) {
+                        if ([dict[key] isEqualToString:level]) {
+                            dpiValue = key;
+                            break;;
+                        }
+                    }
+                    
+                    AiMouseDeviceInfo *info = [[AiMouseDeviceInfo alloc] init];
+                    info.type = 0;
+                    info.battery_power = [NSString stringWithFormat:@"%d",deviceInfo.batteryValue] ;
+                    info.version = [NSString stringWithFormat:@"%@",deviceInfo.version];
+                    info.CPI_list = CPI_list;
+                    info.CPI = dpiValue;
+                    ws.fullInfo = info;
+                    
                     info.brand = snInfo.brand;
                     info.sn = snInfo.sn;
                     info.mac = snInfo.mac;
+                    if ([[info.brand uppercaseString] isEqualTo:@"D3"]) {
+                        info.type = 1;//D3是键盘
+                    }
                     [ws showLog:info.description];
                     if(ws.getFullInfoCallBack)ws.getFullInfoCallBack(info, nil);
-                }
-                else{
-                    if(ws.getFullInfoCallBack)ws.getFullInfoCallBack(nil,error);
-                    [ws TlwConnectManager:nil connectStateDidChange:false];
-                }
             }];
         }
         else{
-            if(ws.getFullInfoCallBack) ws.getFullInfoCallBack(nil,error);
+            if(ws.getFullInfoCallBack)ws.getFullInfoCallBack(nil,error);
             [ws TlwConnectManager:nil connectStateDidChange:false];
         }
     }];
 }
 
+//- (void)getFullDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))finished{
+//    self.getFullInfoCallBack = finished;
+//    __weak typeof(self) ws = self;
+//    [self getDeviceInfo:^(TlwDeviceInfo *deviceInfo, NSError *error) {
+//        if(deviceInfo != nil){
+//            NSDictionary *dict = @{
+//                @"1200":@"1",
+//                @"1600":@"2",
+//                @"2400":@"3",
+//                @"4800":@"4",
+//            };
+//            
+//            NSString *CPI_list = [[dict allKeys] componentsJoinedByString:@","];
+//            NSString *level = [NSString stringWithFormat:@"%d",deviceInfo.DPI];
+//            NSString *dpiValue = @"1200";
+//            
+//            for (NSString *key in dict) {
+//                if ([dict[key] isEqualToString:level]) {
+//                    dpiValue = key;
+//                    break;;
+//                }
+//            }
+//            
+//            AiMouseDeviceInfo *info = [[AiMouseDeviceInfo alloc] init];
+//            info.type = 0;
+//            info.battery_power = [NSString stringWithFormat:@"%d",deviceInfo.batteryValue] ;
+//            info.version = [NSString stringWithFormat:@"%@",deviceInfo.version];
+//            info.CPI_list = CPI_list;
+//            info.CPI = dpiValue;
+//            ws.fullInfo = info;
+//            
+//            [ws getSnInfo:^(TlwSnInfo *snInfo, NSError *error) {
+//                if( info != nil){
+//                    info.brand = snInfo.brand;
+//                    info.sn = snInfo.sn;
+//                    info.mac = snInfo.mac;
+//                    if ([[info.brand uppercaseString] isEqualTo:@"D3"]) {
+//                        info.type = 1;//D3是键盘
+//                    }
+//                    [ws showLog:info.description];
+//                    if(ws.getFullInfoCallBack)ws.getFullInfoCallBack(info, nil);
+//                }
+//                else{
+//                    if(ws.getFullInfoCallBack)ws.getFullInfoCallBack(nil,error);
+//                    [ws TlwConnectManager:nil connectStateDidChange:false];
+//                }
+//            }];
+//        }
+//        else{
+//            if(ws.getFullInfoCallBack) ws.getFullInfoCallBack(nil,error);
+//            [ws TlwConnectManager:nil connectStateDidChange:false];
+//        }
+//    }];
+//}
+
 
 /// 设置长按滚轮弹出网页开关
 /// - Parameters:
             info.batteryState = batteryState;
             info.batteryValue = batteryValue;
             [self showLog:info.description];
+            [self removeSendTimer];
             if(self.getMouseInfoCallBack)self.getMouseInfoCallBack(info, nil);
             break;
         }
             info.batteryState = batteryState;
             info.batteryValue = batteryValue;
             [self showLog:info.description];
+            [self removeSendTimer];
             if(self.getMouseInfoCallBack)self.getMouseInfoCallBack(info, nil);
             break;
         }
     NSString *replacedString = [text stringByReplacingOccurrencesOfString:@"\0" withString:@"0"];
     return replacedString;
 }
+
+#pragma mark - timer
+- (void)addSendTimer{
+    [self removeSendTimer];
+    self.timer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(timerAction) userInfo:nil repeats:true];
+    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
+}
+- (void)removeSendTimer{
+    if (self.timer && [self.timer isValid]) {
+        [self.timer invalidate];
+    }
+}
+
+- (void)timerAction{
+    [self removeSendTimer];
+    if(self.getMouseInfoCallBack)self.getMouseInfoCallBack(nil, [NSError errorWithDomain:@"" code:400 userInfo:@{@"msg":@"请求超时"}]);
+}
 @end