From: liangzhenying <867174124@qq.com> Date: Mon, 1 Apr 2024 09:56:47 +0000 (+0800) Subject: USB鉴权通讯调试 X-Git-Tag: 阿里鉴权~4 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=f8b45e53f8c63faf4280ab797b708f749b1a05d8;p=mirrors%2FMouseSdk-MacOS.git USB鉴权通讯调试 --- diff --git "a/Document/AiMouseSdk\346\216\245\345\217\243\346\226\207\346\241\243.md" "b/Document/AiMouseSdk\346\216\245\345\217\243\346\226\207\346\241\243.md" index ca77af9..f70e522 100644 --- "a/Document/AiMouseSdk\346\216\245\345\217\243\346\226\207\346\241\243.md" +++ "b/Document/AiMouseSdk\346\216\245\345\217\243\346\226\207\346\241\243.md" @@ -9,6 +9,7 @@ | 1.0.0 | 初始版本 | 梁振营 | 2024-03-8 | | 1.0.1 | 鼠标按键指令修改 | 梁振营 | 2024-03-18 | | 1.0.2 | 鉴权流程修改,只有鉴权成功了,SDK相关功能才可以使用 | 梁振营 | 2024-03-19 | +| 1.0.3 | 支持USB通讯 | 梁振营 | 2024-04-01 | @@ -22,19 +23,30 @@ ## 相关权限配置 -因为sdk用到蓝牙权限,所以需要在info.plist进行相关配置 +因为sdk用到蓝牙权限、网络、语音等功能,info.plist和沙盒需要进行相关权限设置 ```xml NSBluetoothAlwaysUsageDescription -App需要您的同意,才能访问蓝牙 -``` +要打开蓝牙才能使用AI功能哦 + +Privacy - Microphone Usage Description +要打开麦克风才能使用AI功能哦 +``` +![image-20240401162536522](/Users/apple/Library/Application Support/typora-user-images/image-20240401162536522.png) ## SDK相关接口 ```objective-c +/// 单利 ++(AiMouse *)shared; + +/// 切换连接类型 +/// - Parameter type: 连接类型 +- (void)switchConnect:(AiMouseConnectType)type; + /// 开始鉴权 /// - Parameter finished: 鉴权结果回调 - (void)startAuthentication:(void (^)(AiMouseAuthState state))finished; @@ -77,9 +89,9 @@ /// 鼠标按键指令回调 /// - Parameter data: 数据。 -/// M 键 短按0x42;长按按下(开始录音)0x25, 长按抬起(结束录音) 0x26; -/// AI键 短按0x43 ,长按按下(开始录音)0x27, 长按抬起(结束录音) 0x28; -/// 语音键 按下(开始录音) 0x31,弹起(结束录音)0x32; +/// 前 第一次单击31(开始录音), 第二次单击32(结束录音) , 按下21(开始录音)抬起22(结束录音) +/// 中 单击42, 按下25(开始录音)抬起26(结束录音) +/// 后 单击43,按下27(开始录音)抬起28(结束录音) /// 其他未定义 - (void)aiMouseSendCmdData:(NSData *)data; @@ -88,177 +100,541 @@ - (void)aiMouseSendRecordData:(NSData *)data; ``` -## 示例 - -- 蓝牙服务特征 - - ```objective-c - // 服务id - #define kServiceUUID @"FFF1" - //ai特征 - #define kAiUUID @"0783B03E-8535-B5A0-7140-A304D2194CB8" - //鉴权特征 - #define kAuthUUID @"0783B73E-8535-B5A0-7140-A304D2194CB7" - //设备信息特征 - #define kDeviceInfoUUID @"0783B63E-8535-B5A0-7140-A304D2495CB6" - ``` - - - - - -1. 设置代理 - - ```objective-c - [AiMouse shared].delegate = self; - ``` - -2. 查找对应特征,订阅 - - ``` - // 发现特征 - - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { - for (CBCharacteristic *characteristic in service.characteristics){ - if ([characteristic.UUID.UUIDString isEqualToString:kAuthUUID]) { - //鉴权特征 - self.authCha = characteristic; - [peripheral setNotifyValue:YES forCharacteristic:characteristic]; - //找到鉴权特征后,一定要调用鉴权接口开始鉴权。只有鉴权通过了,sdk相关功能才可以使用 - [[AiMouse shared] startAuthentication:^(AiMouseAuthState state) { - [self showLog:[NSString stringWithFormat:@"鉴权结果 = %@",@(state)]]; - if(self.authCallBack){ - self.authCallBack(state == AiMouseAuthState_Success); - } - }]; - } - else if ([characteristic.UUID.UUIDString isEqualToString:kAiUUID]) { - //AI特征 - self.aiCha = characteristic; - [peripheral setNotifyValue:YES forCharacteristic:characteristic]; - } - else if ([characteristic.UUID.UUIDString isEqualToString:kDeviceInfoUUID]) { - //设备信息特征 - self.deviceInfoCha = characteristic; - [peripheral setNotifyValue:YES forCharacteristic:characteristic]; - } - } - } - ``` - - - -3. 收到设备传输过来的数据,传给sdk处理 - - ```objective-c - //收到蓝牙数据 - - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { - NSData *data = characteristic.value; - [self showLog:[NSString stringWithFormat:@"[receive] %@",[AiMouseTools dataToHexString:data]]]; - if([characteristic.UUID.UUIDString isEqualToString:kAuthUUID]){ - //鉴权数据 - [[AiMouse shared] sendAuthDataToSdk:data]; - } - else if([characteristic.UUID.UUIDString isEqualToString:kAiUUID]){ - //AI数据 - [[AiMouse shared] sendAiDataToSdk:data]; - } - else if([characteristic.UUID.UUIDString isEqualToString:kDeviceInfoUUID]){ - //设备信息数据 - [[AiMouse shared] sendDeviceDataToSdk:data]; - } - } - - ``` - - sdk代理回调 - - ```objective-c - /// 鉴权数据回调,需要将此数据转发给蓝牙设备 - /// - Parameter data: 数据 - - (void)aiMouseSendAuthData:(NSData *)data{ - [self showLog:[NSString stringWithFormat:@"[send] %@",[AiMouseTools dataToHexString:data]]]; - [self.connectPeripheral writeValue:data forCharacteristic:self.authCha type:CBCharacteristicWriteWithoutResponse]; - } - - - /// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备 - /// - Parameter data: 数据 - -(void)aiMouseSendDeviceInfoData:(NSData *)data{ - [self showLog:[NSString stringWithFormat:@"[send] %@",[AiMouseTools dataToHexString:data]]]; - [self.connectPeripheral writeValue:data forCharacteristic:self.deviceInfoCha type:CBCharacteristicWriteWithoutResponse]; - } - - /// 鼠标按键指令回调 - /// - Parameter data: 数据。 - /// M 键 短按0x42;长按按下(开始录音)0x25, 长按抬起(结束录音) 0x26; - /// AI键 短按0x43 ,长按按下(开始录音)0x27, 长按抬起(结束录音) 0x28; - /// 语音键 按下(开始录音) 0x31,弹起(结束录音)0x32; - /// 其他未定义 - - (void)aiMouseSendCmdData:(NSData *)data{ - uint8 cmd; - [data getBytes:&cmd length:1]; - if(cmd == 0x25){ - [self showLog:@"M键开始录音"]; - self.recordData = [[NSMutableData alloc] init]; - } - else if(cmd == 0x26){ - [self showLog:@"M键结束录音"]; - [self finishRecored:self.recordData]; - } - else if(cmd == 0x27){ - [self showLog:@"AI键开始录音"]; - self.recordData = [[NSMutableData alloc] init]; - } - else if(cmd == 0x28){ - [self showLog:@"AI键结束录音"]; - [self finishRecored:self.recordData]; - } - else if(cmd == 0x31){ - [self showLog:@"语音键开始录音"]; - self.recordData = [[NSMutableData alloc] init]; - } - else if(cmd == 0x32){ - [self showLog:@"语音键结束录音"]; - [self finishRecored:self.recordData]; - } - else{ - [self showLog:@"未定义指令!!!!!!!!"]; - } - } - /// 录音回调 - /// - Parameter data: pcm格式语音数据 - - (void)aiMouseSendRecordData:(NSData *)data{ - [self.recordData appendData:data]; - } - ``` - - 获取设备信息 - -- 获取设备信息 - - ``` - [[AiMouse shared] getDeviceInfo:^(AiMouseDeviceInfo *deviceInfo, NSError *error) { - - }]; - ``` - - - -- 设置PCI - - ``` - [[AiMouse shared] setCPI:1000 completation:^(BOOL isSuccess, NSError *error) { - - }]; - ``` - - + + +## 蓝牙示例 + +```objective-c + // +// BleManager.m +// AliIotSdkDemo +// +// Created by incar on 2024/1/30. +// + +#import "BleManager.h" +#import +#import "Config.h" + +// 服务id +#define kServiceUUID @"FFF1" +//ai特征 +#define kAiUUID @"0783B03E-8535-B5A0-7140-A304D2194CB8" +//鉴权特征 +#define kAuthUUID @"0783B73E-8535-B5A0-7140-A304D2194CB7" +//设备信息特征 +#define kDeviceInfoUUID @"0783B63E-8535-B5A0-7140-A304D2495CB6" + +@interface BleManager () +@property(nonatomic, strong) CBCentralManager *centralManager;///蓝牙管理 +@property(nonatomic, strong) CBPeripheral *connectPeripheral;//连接的设备 +@property(nonatomic, strong) CBCharacteristic *authCha;//鉴权特征 +@property(nonatomic, strong) CBCharacteristic *aiCha;//ai特征 +@property(nonatomic, strong) CBCharacteristic *deviceInfoCha;//设备信息特征 +@property (nonatomic,strong) NSMutableData *recordData;//录音的数据 +@end + +@implementation BleManager ++(BleManager *)shared{ + static BleManager *manager = nil; + static dispatch_once_t oncePredicate; + dispatch_once(&oncePredicate, ^{ + manager = [[BleManager alloc]init]; + }); + return manager; +} + +- (instancetype)init{ + self = [super init]; + if (self) { + self.centralManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil]; + } + return self; +} + +#pragma mark - CBCentralManagerDelegate +- (void)centralManagerDidUpdateState:(nonnull CBCentralManager *)central { + [self showLog:[NSString stringWithFormat:@"蓝牙状态 = %@",@(central.state)]]; + switch (central.state) { + case CBManagerStateUnknown: + + break; + case CBManagerStateResetting: + + break; + case CBManagerStateUnsupported: + + break; + case CBManagerStateUnauthorized: + + break; + case CBManagerStatePoweredOff: + + break; + case CBManagerStatePoweredOn: + [self autoConnectDevice]; + break; + } +} + +- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{ +// [self showLog:[NSString stringWithFormat:@"扫描到设备 = %@, data = %@",peripheral,advertisementData]]; + if(self.discoverDevice){ + self.discoverDevice(peripheral); + } +} + +- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{ + [self showLog:[NSString stringWithFormat:@"连接成功 name = %@",peripheral.name]]; + if(self.didConnectDevice){ + self.didConnectDevice(peripheral); + } + peripheral.delegate = self; + [peripheral discoverServices:nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:kDidConnectBleNotification object:nil]; +} +-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{ + [self showLog:[NSString stringWithFormat:@"断开连接。。。%@",error.description]]; + [[NSNotificationCenter defaultCenter] postNotificationName:kDidDisconnectBleNotification object:nil]; + if(self.didDisConnectDevice){ + self.didDisConnectDevice(peripheral); + } + [self autoConnectDevice]; +} +- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{ + [self showLog:[NSString stringWithFormat:@"连接失败。。。%@",error.description]]; +} +#pragma mark - CBPeripheralDelegate +//发现服务 +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { + for (CBService *service in peripheral.services){ + [peripheral discoverCharacteristics:nil forService:service]; + } +} + +// 发现特征 +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { + for (CBCharacteristic *characteristic in service.characteristics){ + if ([characteristic.UUID.UUIDString isEqualToString:kAuthUUID]) { + //鉴权特征 + self.authCha = characteristic; + [peripheral setNotifyValue:YES forCharacteristic:characteristic]; + //切换代理 + [AiMouse shared].delegate = self; + //切换当前连接类型 + [[AiMouse shared] switchConnect:AiMouseConnectType_bluetooth]; + //找到鉴权特征后,一定要调用鉴权接口开始鉴权。只有鉴权通过了,sdk相关功能才可以使用 + [[AiMouse shared] startAuthentication:^(AiMouseAuthState state) { + [self showLog:[NSString stringWithFormat:@"鉴权结果 = %@",@(state)]]; + if(self.authCallBack){ + self.authCallBack(state == AiMouseAuthState_Success); + } + }]; + } + else if ([characteristic.UUID.UUIDString isEqualToString:kAiUUID]) { + //AI特征 + self.aiCha = characteristic; + [peripheral setNotifyValue:YES forCharacteristic:characteristic]; + } + else if ([characteristic.UUID.UUIDString isEqualToString:kDeviceInfoUUID]) { + //设备信息特征 + self.deviceInfoCha = characteristic; + [peripheral setNotifyValue:YES forCharacteristic:characteristic]; + } + } +} +//收到蓝牙数据 +- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { + NSData *data = characteristic.value; + [self showLog:[NSString stringWithFormat:@"[receive] %@",[AiMouseTools dataToHexString:data]]]; + if([characteristic.UUID.UUIDString isEqualToString:kAuthUUID]){ + //鉴权数据 + [[AiMouse shared] sendAuthDataToSdk:data]; + } + else if([characteristic.UUID.UUIDString isEqualToString:kAiUUID]){ + //AI数据 + [[AiMouse shared] sendAiDataToSdk:data]; + } + else if([characteristic.UUID.UUIDString isEqualToString:kDeviceInfoUUID]){ + //设备信息数据 + [[AiMouse shared] sendDeviceDataToSdk:data]; + } +} + +#pragma mark - AiDelegate +/// 鉴权数据回调,需要将此数据转发给蓝牙设备 +/// - Parameter data: 数据 +- (void)aiMouseSendAuthData:(NSData *)data{ + [self showLog:[NSString stringWithFormat:@"[send] %@",[AiMouseTools dataToHexString:data]]]; + [self.connectPeripheral writeValue:data forCharacteristic:self.authCha type:CBCharacteristicWriteWithoutResponse]; +} + + +/// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备 +/// - Parameter data: 数据 +-(void)aiMouseSendDeviceInfoData:(NSData *)data{ + [self showLog:[NSString stringWithFormat:@"[send] %@",[AiMouseTools dataToHexString:data]]]; + [self.connectPeripheral writeValue:data forCharacteristic:self.deviceInfoCha type:CBCharacteristicWriteWithoutResponse]; +} + +/// 鼠标按键指令回调 +/// - Parameter data: 数据。 +/// 前 第一次单击31(开始录音), 第二次单击32(结束录音) , 按下21(开始录音)抬起22(结束录音) +/// 中 单击42, 按下25(开始录音)抬起26(结束录音) +/// 后 单击43,按下27(开始录音)抬起28(结束录音) +/// 其他未定义 +- (void)aiMouseSendCmdData:(NSData *)data{ + uint8 cmd; + [data getBytes:&cmd length:1]; + [self showLog:[NSString stringWithFormat:@"收到指令 = %X",cmd]]; + + if(cmd == 0x31 || cmd == 0x21 || cmd == 0x25 ||cmd == 0x27){ + [self showLog:@"开始录音"]; + self.recordData = [[NSMutableData alloc] init]; + } + else if(cmd == 0x32 || cmd == 0x22 || cmd == 0x26 ||cmd == 0x28){ + [self showLog:@"结束录音"]; + [self finishRecored:self.recordData]; + } +} + +/// 录音回调 +/// - Parameter data: pcm格式语音数据 +- (void)aiMouseSendRecordData:(NSData *)data{ + [self.recordData appendData:data]; +} + +#pragma mark - public +/// 连接设备 +- (void)startScanDevice{ + [self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : [NSNumber numberWithBool:NO]}]; +} + +/// 扫描设备 +- (void)stopScanDevice{ + [self.centralManager stopScan]; +} + +/// 连接设备 +- (void)connectPeripheral:(CBPeripheral *)peripheral{ + self.connectPeripheral = peripheral; + [self.centralManager connectPeripheral:peripheral options:@{CBConnectPeripheralOptionNotifyOnConnectionKey : [NSNumber numberWithBool:YES]}]; +} + +/// 获取设备信息 +- (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo * _Nonnull, NSError * _Nonnull))completation{ + [[AiMouse shared] getDeviceInfo:completation]; +} +#pragma mark - other +//自动连接,获取已配对的蓝牙,取第一个连接 +- (void)autoConnectDevice{ + //如果是已连接或者正在连接,则不再重连 + if (self.connectPeripheral && (self.connectPeripheral.state == CBPeripheralStateConnected || self.connectPeripheral.state == CBPeripheralStateConnecting)) { + return; + } + NSArray *devices = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:kServiceUUID]]]; + if (devices.count > 0) { + CBPeripheral *peripheral = devices[0]; + [self showLog:[NSString stringWithFormat:@"匹配过的设备%@",peripheral.name]]; + [self connectPeripheral:peripheral]; + } + // 10s自动重连 + [self performSelector:@selector(autoConnectDevice) withObject:nil afterDelay:10]; +} +- (void)showLog:(NSString *)log{ + NSLog(@"%@",log); +} + +//将录音数据保存 +- (void)finishRecored:(NSData *)data{ + NSString *doc = NSTemporaryDirectory(); + NSString *fullPath = [NSString stringWithFormat:@"%@1.pcm",doc]; + NSError *err; + [data writeToFile:fullPath options:NSDataWritingAtomic error:&err]; + if (err) { + [self showLog:[NSString stringWithFormat:@"录音保存失败 %@",err.description]]; + } + else{ + [self showLog:[NSString stringWithFormat:@"录音保存成功 path = %@",fullPath]]; + } +} +@end + +``` + + + +## USB示例 + +​ + +```objective-c +// +// HidManager.m +// MouseSdk +// +// Created by incar on 2024/3/26. +// + +#import "HidManager.h" +#include +#include +#import +#import "Config.h" + +//供应商id +const long vendorID = 0x248a; +//产品id +const long productID = 0xca08; + +@interface HidManager () + +@property(nonatomic, assign) IOHIDManagerRef hidManager;///hid管理 +@property(nonatomic, assign) IOHIDDeviceRef authCha;//鉴权通道 +@property(nonatomic, assign) IOHIDDeviceRef aiCha;//ai通道 +@property(nonatomic, assign) IOHIDDeviceRef deviceInfoCha;//设备信息通道 +@property (nonatomic,strong) NSMutableData *recordData;//录音的数据 +@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) { + [self initHid]; + [self open]; + } + return self; +} + +- (void)initHid{ + +} + +- (void)open{ + self.hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + IOHIDManagerScheduleWithRunLoop(self.hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode); + IOReturn ret = IOHIDManagerOpen(self.hidManager, 0L); + if (ret != kIOReturnSuccess) { + NSLog(@"打开设备失败!"); + }else{ + NSLog(@"打开设备成功!"); + } + //设置匹配设备 + 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{ + IOReturn ret = IOHIDManagerClose(self.hidManager, 0); + if (ret != kIOReturnSuccess) { + NSLog(@"关闭设备失败!"); + }else{ + NSLog(@"关闭设备成功!"); + } +} + +#pragma mark - Hid CallBack +/// 匹配到设备回调 +static void hidAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) { + uint32_t vid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey)); + uint32_t pid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey)); + uint32_t PrimaryUsagePage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsagePageKey)); + uint32_t PrimaryUsage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsageKey)); + NSLog(@"vid = %u, pid = %u, PrimaryUsagePage = %u, PrimaryUsage = %u,",vid,pid,PrimaryUsagePage,PrimaryUsage); + NSLog(@"发现设备 %@\n ",inIOHIDDeviceRef); + + // PrimaryUsagePage=1 PrimaryUsage=0,设备信息 + // PrimaryUsagePage=1 PrimaryUsage=6,鉴权 + // PrimaryUsagePage=65283 PrimaryUsage=0,ai + if(PrimaryUsagePage == 1 && PrimaryUsage == 0){ + //设备信息 + [HidManager shared].deviceInfoCha = inIOHIDDeviceRef; + //鉴权 + [HidManager shared].authCha = inIOHIDDeviceRef; + //开始鉴权 + [[HidManager shared] startAuthentication]; + } + else if(PrimaryUsagePage == 65283 && PrimaryUsage == 0){ + //ai + [HidManager shared].aiCha = inIOHIDDeviceRef; + } + //注册消息回调 + unsigned char InputBuffer[128]; + IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), hidReceiveData, NULL); +} + +/// 设备移除回调 +static void hidDisAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) { + NSLog(@"拔出设备 %@ ",inIOHIDDeviceRef); + uint32_t PrimaryUsagePage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsagePageKey)); + uint32_t PrimaryUsage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsageKey)); + + if(PrimaryUsagePage == 1 && PrimaryUsage == 0){ + [HidManager shared].connectStateCallBack(false); + } +} + +static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDReportType type, uint32_t reportID, uint8_t *report,CFIndex reportLength){ + + [[HidManager shared] showLog:[NSString stringWithFormat:@"[receive] 处理前 %@",[AiMouseTools dataToHexString:[[NSData alloc] initWithBytes:report length:reportLength]]]]; + + NSInteger len = get_data_len(report, reportLength); + NSData *data = [[NSData alloc] initWithBytes:report length:len]; + [[HidManager shared] showLog:[NSString stringWithFormat:@"[receive] 处理后 %@",[AiMouseTools dataToHexString:data]]]; + + uint32_t PrimaryUsagePage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsagePageKey)); + uint32_t PrimaryUsage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsageKey)); + + if(PrimaryUsagePage == 1 && PrimaryUsage == 0){ + [[HidManager shared] showLog:@"device数据"]; + [[AiMouse shared] sendDeviceDataToSdk:data]; + } + else if(PrimaryUsagePage == 65283 && PrimaryUsage == 0){ + [[HidManager shared] showLog:@"AI数据"]; + [[AiMouse shared] sendAiDataToSdk:data]; + } +} +#pragma mark - AiDelegate +/// 鉴权数据回调,需要将此数据转发给蓝牙设备 +/// - Parameter data: 数据 +- (void)aiMouseSendAuthData:(NSData *)data{ + [self sendData:data toDevice:self.authCha]; +} + +/// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备 +/// - Parameter data: 数据 +-(void)aiMouseSendDeviceInfoData:(NSData *)data{ + [self sendData:data toDevice:self.deviceInfoCha]; +} + +/// 鼠标按键指令回调 +/// - Parameter data: 数据。 +/// 前 第一次单击31(开始录音), 第二次单击32(结束录音) , 按下21(开始录音)抬起22(结束录音) +/// 中 单击42, 按下25(开始录音)抬起26(结束录音) +/// 后 单击43,按下27(开始录音)抬起28(结束录音) +/// 其他未定义 +- (void)aiMouseSendCmdData:(NSData *)data{ + uint8 cmd; + [data getBytes:&cmd length:1]; + [self showLog:[NSString stringWithFormat:@"收到指令 = %X",cmd]]; + + if(cmd == 0x31 || cmd == 0x21 || cmd == 0x25 ||cmd == 0x27){ + [self showLog:@"开始录音"]; + self.recordData = [[NSMutableData alloc] init]; + } + else if(cmd == 0x32 || cmd == 0x22 || cmd == 0x26 ||cmd == 0x28){ + [self showLog:@"结束录音"]; + [self finishRecored:self.recordData]; + } +} +/// 录音回调 +/// - Parameter data: pcm格式语音数据 +- (void)aiMouseSendRecordData:(NSData *)data{ + [self.recordData appendData:data]; +} + +#pragma mark - public +-(void)startAuthentication{ + //连上设备 + [HidManager shared].connectStateCallBack(true); + //设置代理 + [AiMouse shared].delegate = self; + //切换当前连接类型 + [[AiMouse shared] switchConnect:AiMouseConnectType_hid]; + //找到鉴权特征后,一定要调用鉴权接口开始鉴权。只有鉴权通过了,sdk相关功能才可以使用 + [self showLog:@"开始鉴权"]; + [[AiMouse shared] startAuthentication:^(AiMouseAuthState state) { + [self showLog:[NSString stringWithFormat:@"鉴权结果 = %@",@(state)]]; + if(self.authCallBack){ + self.authCallBack(state == AiMouseAuthState_Success); + } + }]; +} +/// 获取设备信息 +- (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo * _Nonnull, NSError * _Nonnull))completation{ + [[AiMouse shared] getDeviceInfo:completation]; +} + +/// 发送数据给设备 +-(void)sendData:(NSData *)data toDevice:(IOHIDDeviceRef)device{ + if(device == nil){ + [self showLog:@"请先连上设备"]; + return; + } + [self showLog:[NSString stringWithFormat:@"开始发送[send] %@\n%@",[AiMouseTools dataToHexString:data],[AiMouseTools dataToUtf8String:data]]]; + + IOReturn ret = IOHIDDeviceSetReport(device, kIOHIDReportTypeOutput, 0, data.bytes, data.length); + if (ret != kIOReturnSuccess) { + [self showLog:[NSString stringWithFormat:@"发送失败! code = %d",ret]]; + }else{ + [self showLog:@"发送成功!"]; + } +} +//将录音数据保存 +- (void)finishRecored:(NSData *)data{ + NSString *doc = NSTemporaryDirectory(); + NSString *fullPath = [NSString stringWithFormat:@"%@1.pcm",doc]; + NSError *err; + [data writeToFile:fullPath options:NSDataWritingAtomic error:&err]; + if (err) { + [self showLog:[NSString stringWithFormat:@"录音保存失败 %@",err.description]]; + } + else{ + [self showLog:[NSString stringWithFormat:@"录音保存成功 path = %@",fullPath]]; + } +} +- (void)showLog:(NSString *)log{ + NSLog(@"%@",log); +} + +/// 实际到数据长度 +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; +} + +/// 获取对应属性值 +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) { + NSLog(@"get %@ failed.", inKey); + } + } + } + return outValue; +} +@end + +``` ## 注意事项 -- 鉴权数据使用的是鉴权特征,走鉴权接口;设备信息数据使用的是设备信息特征,走设备信息接口;AI数据使用的是AI特征,走AI接口。 -- 只有鉴权成功了以后,AI相关功能才可用。authState鉴权状态,默认是Unknow。所以必须在连上蓝牙设备找到鉴权特征后,需要主动调用startAuthentication方法去鉴权。(只有鉴权成功,AI键,语音键、M键才可用) +- 鉴权数据使用的是鉴权,走鉴权接口;设备信息数据使用的是设备信息通道,走设备信息接口;AI数据使用的是AI通道,走AI接口。 +- 只有鉴权成功了以后,AI相关功能才可用。authState鉴权状态,默认是Unknow。所以必须在连上蓝牙设备找到鉴权特征后,需要主动调用startAuthentication方法去鉴权。(只有鉴权成功,AI功能才可用) - SDK只封装了蓝牙相关数据处理,APP自己维护蓝牙设备的扫描连接。蓝牙设备一段时间没有任何操作的话,会自动断开连接。APP可以在检测到断开后重连。 +- 当切换蓝牙或者USB,需要调用switchConnect切换连接类型。 diff --git a/MouseSdk/AiMouseSdk/AiAuthManager.m b/MouseSdk/AiMouseSdk/AiAuthManager.m index 64b4276..0a9b99a 100644 --- a/MouseSdk/AiMouseSdk/AiAuthManager.m +++ b/MouseSdk/AiMouseSdk/AiAuthManager.m @@ -24,7 +24,7 @@ _bizbusManager.bleSendDataDelegate = self; _bizbusManager.appVersion = @"--"; _bizbus_connect_queue = dispatch_queue_create("bizbus_connect_queue", DISPATCH_QUEUE_SERIAL); - [self enableBizbusLog:true]; + [self enableBizbusLog:false]; } return self; } diff --git a/MouseSdk/AiMouseSdk/AiFrameManager.m b/MouseSdk/AiMouseSdk/AiFrameManager.m index 056c7f8..db7dd64 100644 --- a/MouseSdk/AiMouseSdk/AiFrameManager.m +++ b/MouseSdk/AiMouseSdk/AiFrameManager.m @@ -7,6 +7,7 @@ #import "AiFrameManager.h" #import "AiMouseTools.h" +#import "AiMouseConfig.h" @interface AiFrameManager() @property (nonatomic,strong)NSMutableData *recvData; @@ -14,14 +15,15 @@ @implementation AiFrameManager - (void)didReceiveFrameData:(NSData *)data{ - NSString *str = [AiMouseTools dataToUtf8String:data]; - if ([str isEqualTo:@"-$$"]) { + NSString *str = [[AiMouseTools dataToHexString:data] uppercaseString]; + [self showLog:[NSString stringWithFormat:@"分段 = %@ 内容 = %@",str,[AiMouseTools dataToUtf8String:data]]]; + if ([str hasPrefix:@"2D242400"]) { //开始 self.recvData = [[NSMutableData alloc] init]; } - else if([str isEqualTo:@"$$-\n"]){ + else if([str hasSuffix:@"24242D0A00"]){ NSString *str1 = [AiMouseTools dataToHexString:self.recvData]; - NSLog(@"收到完整数据 = %@",str1); + [self showLog:[NSString stringWithFormat:@"完整数据 = %@",str1]]; //结束 if(self.didReceiveFullData){ self.didReceiveFullData(self.recvData); @@ -29,27 +31,39 @@ } else{ //数据 - [self.recvData appendData:data]; + NSData *subData; + if([str hasSuffix:@"00"]){ + subData = [data subdataWithRange:NSMakeRange(0, data.length - 1)]; + } + else{ + subData = data; + } + [self showLog:[NSString stringWithFormat:@"拼接数据 = %@",[AiMouseTools dataToHexString:subData]]]; + [self.recvData appendData:subData]; } } - (void)didReceiveHidAuthData:(NSData *)data{ - NSString *str = [AiMouseTools dataToHexString:data]; - NSLog(@"收到数据 = %@",str); + NSString *str = [[AiMouseTools dataToHexString:data] uppercaseString]; + [self showLog:[NSString stringWithFormat:@"分段 = %@ 内容 = %@",str,[AiMouseTools dataToUtf8String:data]]]; if ([str hasPrefix:@"2D2424"]) { + self.recvData = [[NSMutableData alloc] init]; //开始 - NSData *subData = [data subdataWithRange:NSMakeRange(3, data.length - 4)]; - NSString *str1 = [AiMouseTools dataToHexString:subData]; - NSLog(@"实收数据 = %@",str1); - self.recvData = [[NSMutableData alloc] initWithData:subData]; + NSData *subData = [data subdataWithRange:NSMakeRange(3, data.length - 3)]; + if(subData.length > 0){ + [self showLog:[NSString stringWithFormat:@"拼接数据 = %@",[AiMouseTools dataToHexString:subData]]]; + [self.recvData appendData:subData]; + } + } else if([str hasSuffix:@"24242D0A"]){ - NSData *subData = [data subdataWithRange:NSMakeRange(0, data.length - 5)]; - NSString *str1 = [AiMouseTools dataToHexString:subData]; - NSLog(@"实收数据 = %@",str1); - [self.recvData appendData:subData]; - NSString *all = [AiMouseTools dataToUtf8String:self.recvData]; - NSLog(@"完整数据 %@\n %@",[AiMouseTools dataToHexString:self.recvData],all); + NSData *subData = [data subdataWithRange:NSMakeRange(0, data.length - 4)]; + if(subData.length > 0){ + [self showLog:[NSString stringWithFormat:@"拼接数据 = %@",[AiMouseTools dataToHexString:subData]]]; + [self.recvData appendData:subData]; + } + NSString *str1 = [AiMouseTools dataToHexString:self.recvData]; + [self showLog:[NSString stringWithFormat:@"完整数据 = %@",str1]]; //结束 if(self.didReceiveFullData){ self.didReceiveFullData(self.recvData); @@ -57,10 +71,19 @@ } else{ //数据 - NSData *subData = [data subdataWithRange:NSMakeRange(0, data.length - 1)]; - NSString *str1 = [AiMouseTools dataToHexString:subData]; - NSLog(@"实收数据 = %@",str1); - [self.recvData appendData:data]; + NSData *subData; + if([str hasSuffix:@"00"]){ + subData = [data subdataWithRange:NSMakeRange(0, data.length - 1)]; + } + else{ + subData = data; + } + [self showLog:[NSString stringWithFormat:@"拼接数据 = %@",[AiMouseTools dataToHexString:subData]]]; + [self.recvData appendData:subData]; } } + +- (void)showLog:(NSString *)log{ + NSLog(@"%@",log); +} @end diff --git a/MouseSdk/AiMouseSdk/AiMouse.h b/MouseSdk/AiMouseSdk/AiMouse.h index a5e4b9b..c8f174b 100644 --- a/MouseSdk/AiMouseSdk/AiMouse.h +++ b/MouseSdk/AiMouseSdk/AiMouse.h @@ -47,7 +47,7 @@ typedef NS_ENUM(NSInteger,AiMouseAuthState) { @property (nonatomic, readonly) NSString *version;/// 版本号 @property (nonatomic, weak) id delegate;/// 代理 @property (nonatomic, readonly) AiMouseConnectType connectType;//连接类型 -@property (nonatomic, readonly) AiMouseAuthState authState;/// 鉴权状态,默认是Unknow。所以必须在连上蓝牙设备找到鉴权特征后,需要主动调用startAuthentication方法去鉴权。(只有鉴权成功,AI键,语音键、M键才可用) +@property (nonatomic, readonly) AiMouseAuthState authState;/// 鉴权状态,默认是Unknow。所以必须在连上蓝牙设备找到鉴权特征后,需要主动调用startAuthentication方法去鉴权。(只有鉴权成功,AI功能才可用) /// 单利 +(AiMouse *)shared; diff --git a/MouseSdk/AiMouseSdk/AiMouse.m b/MouseSdk/AiMouseSdk/AiMouse.m index 9a3f06b..0a98cb6 100644 --- a/MouseSdk/AiMouseSdk/AiMouse.m +++ b/MouseSdk/AiMouseSdk/AiMouse.m @@ -47,7 +47,7 @@ } -(NSString *)version{ - return @"1.0.3"; + return @"1.0.4"; } -(AiFrameManager *)frameManager{ if (!_frameManager) { @@ -279,8 +279,13 @@ } } - (void)sendDeviceInfoData:(NSData *)data{ + NSString *str = [AiMouseTools dataToUtf8String:data]; + NSMutableString *str1 = [NSMutableString stringWithString:str]; + NSString *sendStr = [NSString stringWithFormat:@"-$$%@$$-\n",str1]; + NSData *sendData = [sendStr dataUsingEncoding:NSUTF8StringEncoding]; + [self showLog:[NSString stringWithFormat:@"发送的设备信息数据 = %@",sendStr]]; if (self.delegate) { - [self.delegate aiMouseSendDeviceInfoData:data]; + [self.delegate aiMouseSendDeviceInfoData:sendData]; } } diff --git a/MouseSdk/AiMouseSdk/AiRecordManager.m b/MouseSdk/AiMouseSdk/AiRecordManager.m index 5a6b216..b0c9e5f 100644 --- a/MouseSdk/AiMouseSdk/AiRecordManager.m +++ b/MouseSdk/AiMouseSdk/AiRecordManager.m @@ -127,7 +127,7 @@ } - (void)openSettings{ - NSURL *url = [NSURL URLWithString:@""]; +// NSURL *url = [NSURL URLWithString:@""]; } - (void)showLog:(NSString *)log{ diff --git a/MouseSdk/AliIotConnectKitSDK/AliIotConnectKit/Mqtt/IotMqtt/IotMqttManager_C.swift b/MouseSdk/AliIotConnectKitSDK/AliIotConnectKit/Mqtt/IotMqtt/IotMqttManager_C.swift index ad8f245..d652003 100755 --- a/MouseSdk/AliIotConnectKitSDK/AliIotConnectKit/Mqtt/IotMqtt/IotMqttManager_C.swift +++ b/MouseSdk/AliIotConnectKitSDK/AliIotConnectKit/Mqtt/IotMqtt/IotMqttManager_C.swift @@ -161,6 +161,7 @@ class IotMqttManager_C: NSObject, SdkMqttService_C { } let legacyConfig = IotMqttLegacyConfig_C.init(productKey: config.productKey, deviceName: config.deviceName, password: config.password, timestamp: config.timestamp) +// print("开始请求: clientId =\(legacyConfig.clientId) userName = \(legacyConfig.username) passWord = \(legacyConfig.password) url = \(config.server) port = \(config.port)") let initSdk:() -> () = { [self] in let result = mqttShared.mqttLegacyInit(legacyConfig.clientId, userName: legacyConfig.username, passWord: legacyConfig.password, hostUrl: config.server, port: config.port) diff --git a/MouseSdk/MouseSdk.xcodeproj/project.pbxproj b/MouseSdk/MouseSdk.xcodeproj/project.pbxproj index 2dc25fc..05904bf 100644 --- a/MouseSdk/MouseSdk.xcodeproj/project.pbxproj +++ b/MouseSdk/MouseSdk.xcodeproj/project.pbxproj @@ -273,6 +273,7 @@ 18BF1E892B8362D300B8D90F /* AiMouseSdk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiMouseSdk.h; sourceTree = ""; }; 18BF8F4C2BA9A7A4008F6933 /* AiMouseDeviceInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiMouseDeviceInfo.h; sourceTree = ""; }; 18BF8F4D2BA9A7A4008F6933 /* AiMouseDeviceInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiMouseDeviceInfo.m; sourceTree = ""; }; + 18C31D6F2BBAA6CC0089D656 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 18CB080B2BA401D0005F5854 /* liblzma.5.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = liblzma.5.tbd; path = usr/lib/liblzma.5.tbd; sourceTree = SDKROOT; }; 18CB08102BA40282005F5854 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; 18CB08112BA40282005F5854 /* buffersrc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffersrc.h; sourceTree = ""; }; @@ -511,6 +512,7 @@ 18BF1DCC2B81AB7C00B8D90F /* MouseSdk */ = { isa = PBXGroup; children = ( + 18C31D6F2BBAA6CC0089D656 /* Info.plist */, 18BF1E202B83066200B8D90F /* BleManager.h */, 18BF1E212B83066200B8D90F /* BleManager.m */, 1867E5A72BB2706F008FC5FB /* HidManager.h */, @@ -1390,10 +1392,11 @@ "$(PROJECT_DIR)/framework", ); GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "要打开蓝牙才能继续使用APP哦"; + INFOPLIST_FILE = MouseSdk/Info.plist; + INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "要打开蓝牙才能使用AI功能哦"; INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSMainStoryboardFile = Main; - INFOPLIST_KEY_NSMicrophoneUsageDescription = "要打开麦克风才能继续使用APP哦"; + INFOPLIST_KEY_NSMicrophoneUsageDescription = "要打开麦克风才能使用AI功能哦"; INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1427,10 +1430,11 @@ "$(PROJECT_DIR)/framework", ); GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "要打开蓝牙才能继续使用APP哦"; + INFOPLIST_FILE = MouseSdk/Info.plist; + INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "要打开蓝牙才能使用AI功能哦"; INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSMainStoryboardFile = Main; - INFOPLIST_KEY_NSMicrophoneUsageDescription = "要打开麦克风才能继续使用APP哦"; + INFOPLIST_KEY_NSMicrophoneUsageDescription = "要打开麦克风才能使用AI功能哦"; INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate b/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate index 1b585d5..ae341d2 100644 Binary files a/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate and b/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 8cf9284..b9bdb28 100644 --- a/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/MouseSdk/MouseSdk.xcworkspace/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -32,5 +32,68 @@ stopOnStyle = "0"> + + + + + + + + + + + + diff --git a/MouseSdk/MouseSdk/HidManager.h b/MouseSdk/MouseSdk/HidManager.h index c1e4e62..147e693 100644 --- a/MouseSdk/MouseSdk/HidManager.h +++ b/MouseSdk/MouseSdk/HidManager.h @@ -20,6 +20,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)getDeviceInfo:(void (^)(AiMouseDeviceInfo *deviceInfo,NSError *error))completation; +/// 鉴权 -(void)startAuthentication; @end diff --git a/MouseSdk/MouseSdk/HidManager.m b/MouseSdk/MouseSdk/HidManager.m index 838d5d1..c164014 100644 --- a/MouseSdk/MouseSdk/HidManager.m +++ b/MouseSdk/MouseSdk/HidManager.m @@ -8,16 +8,20 @@ #import "HidManager.h" #include #include - #import #import "Config.h" +//供应商id +const long vendorID = 0x248a; +//产品id +const long productID = 0xca08; + @interface HidManager () @property(nonatomic, assign) IOHIDManagerRef hidManager;///hid管理 -@property(nonatomic, assign) IOHIDDeviceRef authCha;//鉴权特征 -@property(nonatomic, assign) IOHIDDeviceRef aiCha;//ai特征 -@property(nonatomic, assign) IOHIDDeviceRef deviceInfoCha;//设备信息特征 +@property(nonatomic, assign) IOHIDDeviceRef authCha;//鉴权通道 +@property(nonatomic, assign) IOHIDDeviceRef aiCha;//ai通道 +@property(nonatomic, assign) IOHIDDeviceRef deviceInfoCha;//设备信息通道 @property (nonatomic,strong) NSMutableData *recordData;//录音的数据 @end @@ -53,15 +57,14 @@ }else{ NSLog(@"打开设备成功!"); } - - const long vendorID = 0x248a; - const long productID = 0xca08; + //设置匹配设备 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); } @@ -75,6 +78,7 @@ } #pragma mark - Hid CallBack +/// 匹配到设备回调 static void hidAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) { uint32_t vid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey)); uint32_t pid = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey)); @@ -91,22 +95,19 @@ static void hidAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOH [HidManager shared].deviceInfoCha = inIOHIDDeviceRef; //鉴权 [HidManager shared].authCha = inIOHIDDeviceRef; + //开始鉴权 [[HidManager shared] startAuthentication]; } - else if(PrimaryUsagePage == 1 && PrimaryUsage == 6){ -// //鉴权 -// [HidManager shared].authCha = inIOHIDDeviceRef; -// [[HidManager shared] startAuthentication]; - } else if(PrimaryUsagePage == 65283 && PrimaryUsage == 0){ //ai [HidManager shared].aiCha = inIOHIDDeviceRef; } - + //注册消息回调 unsigned char InputBuffer[128]; IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef, InputBuffer, sizeof(InputBuffer), hidReceiveData, NULL); } +/// 设备移除回调 static void hidDisAppearDevice(void *inContext,IOReturn inResult,void *inSender,IOHIDDeviceRef inIOHIDDeviceRef) { NSLog(@"拔出设备 %@ ",inIOHIDDeviceRef); uint32_t PrimaryUsagePage = IOHIDDevGetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsagePageKey)); @@ -118,9 +119,12 @@ static void hidDisAppearDevice(void *inContext,IOReturn inResult,void *inSender, } static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDReportType type, uint32_t reportID, uint8_t *report,CFIndex reportLength){ + + [[HidManager shared] showLog:[NSString stringWithFormat:@"[receive] 处理前 %@",[AiMouseTools dataToHexString:[[NSData alloc] initWithBytes:report length:reportLength]]]]; + NSInteger len = get_data_len(report, reportLength); NSData *data = [[NSData alloc] initWithBytes:report length:len]; - [[HidManager shared] showLog:[NSString stringWithFormat:@"[receive] = %@",[AiMouseTools dataToHexString:data]]]; + [[HidManager shared] showLog:[NSString stringWithFormat:@"[receive] 处理后 %@",[AiMouseTools dataToHexString:data]]]; uint32_t PrimaryUsagePage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsagePageKey)); uint32_t PrimaryUsage = IOHIDDevGetUInt32Property(sender, CFSTR(kIOHIDPrimaryUsageKey)); @@ -134,21 +138,6 @@ static void hidReceiveData(void* context, IOReturn result, void* sender, IOHIDRe [[AiMouse shared] sendAiDataToSdk:data]; } } - -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) { - NSLog(@"get %@ failed.", inKey); - } - } - } - - return outValue; -} #pragma mark - AiDelegate /// 鉴权数据回调,需要将此数据转发给蓝牙设备 /// - Parameter data: 数据 @@ -156,7 +145,6 @@ static uint32_t IOHIDDevGetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStr [self sendData:data toDevice:self.authCha]; } - /// 设备信息数据回调,需要将此数据通过设备信息特征转发给蓝牙设备 /// - Parameter data: 数据 -(void)aiMouseSendDeviceInfoData:(NSData *)data{ @@ -191,7 +179,9 @@ static uint32_t IOHIDDevGetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStr #pragma mark - public -(void)startAuthentication{ + //连上设备 [HidManager shared].connectStateCallBack(true); + //设置代理 [AiMouse shared].delegate = self; //切换当前连接类型 [[AiMouse shared] switchConnect:AiMouseConnectType_hid]; @@ -209,6 +199,7 @@ static uint32_t IOHIDDevGetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStr [[AiMouse shared] getDeviceInfo:completation]; } +/// 发送数据给设备 -(void)sendData:(NSData *)data toDevice:(IOHIDDeviceRef)device{ if(device == nil){ [self showLog:@"请先连上设备"]; @@ -240,6 +231,7 @@ static uint32_t IOHIDDevGetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStr NSLog(@"%@",log); } +/// 实际到数据长度 static inline int get_data_len(uint8_t *buf, u_long len) { if (len <= 0 ) return 0; int url_len = 0; @@ -247,4 +239,18 @@ static inline int get_data_len(uint8_t *buf, u_long len) { return url_len; } +/// 获取对应属性值 +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) { + NSLog(@"get %@ failed.", inKey); + } + } + } + return outValue; +} @end diff --git a/MouseSdk/MouseSdk/Info.plist b/MouseSdk/MouseSdk/Info.plist new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/MouseSdk/MouseSdk/Info.plist @@ -0,0 +1,5 @@ + + + + +