diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/Index.ets b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..8d590060bd716dbad2255df4bca667620fd515be --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/Index.ets @@ -0,0 +1,132 @@ +import router from '@ohos.router'; + +@Entry +@Component +struct Index { + @State message: string = 'USB测试'; + @State versionInfo: string = 'version 1.0' + + navigateToAutomation() { + router.pushUrl({ url: 'pages/automation' }); + } + + navigateToUsbInfo() { + router.pushUrl({ url: 'pages/usb_info' }); + } + + navigateToUsbListening() { + router.pushUrl({ url: 'pages/usb_listening' }); + } + + navigateToSplitTest() { + router.pushUrl({ url: 'pages/split_test' }); + } + + navigateToManualTest() { + router.pushUrl({ url: 'pages/manual_test' }); + } + + build() { + Column() { + // Header Section with background image and Huawei icon + Column() { + // Row to place icon and title side by side + Row() { + // Huawei Icon + Image($r('app.media.huawei')) // Use the resource reference for the local icon + .width(60) + .height(60) + .margin({ right: '30px' }) // Add margin to the right of the icon + + // Title + Text(this.message) + .fontSize(36) + .fontWeight(FontWeight.Bold) + .textAlign(TextAlign.Start) // Ensure text starts from the left + .fontColor('#ff000000') + } + .alignItems(VerticalAlign.Center) // Center align items in the row + .margin({ top: '200px', bottom: '20px' }) + + Text(this.versionInfo) + .fontSize(20) + .fontWeight(FontWeight.Bold) + .textAlign(TextAlign.Center) + .fontColor('#ff000000') + .margin({ bottom: '40px' }) + } + .height('30%') + .justifyContent(FlexAlign.Center) + .padding({ top: '20px', bottom: '20px' }) + + // Content Section with buttons + Column() { + Button('USB设备信息及权限获取') + .onClick(this.navigateToUsbInfo) + .backgroundColor('#2196F3') + .fontColor('#FFFFFF') + .fontSize(18) + .borderRadius(8) + .width('80%') + .height('50px') + .margin({ bottom: '20px' }) + .shadow({ color: '#000000', radius: 5, offsetX: 0, offsetY: 2}) + .alignSelf(ItemAlign.Center) + + Button('API自动化测试') + .onClick(this.navigateToAutomation) + .backgroundColor('#2196F3') + .fontColor('#FFFFFF') + .fontSize(18) + .borderRadius(8) + .width('80%') + .height('50px') + .margin({ bottom: '20px' }) + .shadow({ color: '#000000', radius: 5, offsetX: 0, offsetY: 2}) + .alignSelf(ItemAlign.Center) + + Button('插拔事件监听服务') + .onClick(this.navigateToUsbListening) + .backgroundColor('#2196F3') + .fontColor('#FFFFFF') + .fontSize(18) + .borderRadius(8) + .width('80%') + .height('50px') + .margin({ bottom: '20px' }) + .shadow({ color: '#000000', radius: 5, offsetX: 0, offsetY: 2}) + .alignSelf(ItemAlign.Center) + + Button('接口分离测试') + .onClick(this.navigateToSplitTest) + .backgroundColor('#2196F3') + .fontColor('#FFFFFF') + .fontSize(18) + .borderRadius(8) + .width('80%') + .height('50px') + .margin({ bottom: '20px' }) + .shadow({ color: '#000000', radius: 5, offsetX: 0, offsetY: 2}) + .alignSelf(ItemAlign.Center) + + Button('端口信息获取及设备主机切换') + .onClick(this.navigateToManualTest) + .backgroundColor('#2196F3') + .fontColor('#FFFFFF') + .fontSize(18) + .borderRadius(8) + .width('80%') + .height('50px') + .margin({ bottom: '20px' }) + .shadow({ color: '#000000', radius: 5, offsetX: 0, offsetY: 2}) + .alignSelf(ItemAlign.Center) + } + .height('70%') + .justifyContent(FlexAlign.Center) + .padding({ top: '20px', bottom: '20px' }) + } + .width('100%') + .height('100%') + .backgroundColor('#ffffffff') + } +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/automation.ets b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/automation.ets new file mode 100644 index 0000000000000000000000000000000000000000..12425d0dbe8a085fdface3c84d692ab2805b5327 --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/automation.ets @@ -0,0 +1,580 @@ +import usb from '@ohos.usbManager'; +import promptAction from '@ohos.promptAction'; +import router from '@ohos.router'; +import usbManager from '@ohos.enterprise.usbManager'; +import buffer from '@ohos.buffer'; + +interface TestResult { + name: string; + result: string; +} + +interface DeviceDescriptor { + length: number; + descriptorType: number; + usbVersion: number; + deviceClass: number; + deviceSubClass: number; + deviceProtocol: number; + maxPacketSize: number; + vendorId: number; + productId: number; + deviceVersion: number; + manufacturer: number; + product: number; + serialNumber: number; + numConfigurations: number; +} + +enum FunctionType { + NONE = 0, + ACM = 1, + ECM = 2, + HDC = 4, + MTP = 8, + PTP = 16, + RNDIS = 32, + MIDI = 64, + AUDIO_SOURCE = 128, + NCM = 256 +} + +@Entry +@Component +struct Automation { + @State testResults: Array = []; + @State testInProgress: boolean = false; + @State devices: Array = []; + @State selectedDevice: usb.USBDevice | null = null; + @State showDeviceSelection: boolean = true; + @State end: boolean = false; + @State progress: number = 0; + + private bulkResult = new Uint8Array([85,83,66,83,36,0,149,227,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) + private testPipe: usb.USBDevicePipe | null = null; + + aboutToAppear() { + this.refreshDevices(); + } + + refreshDevices() { + this.devices = usb.getDevices(); + if (this.devices.length === 0) { + promptAction.showToast({ message: '没有找到USB设备' }); + } + } + + reset(){ + this.testResults = []; + this.testInProgress = false + this.devices = [] + this.selectedDevice = null + this.end = false + this.progress = 0 + this.testPipe = null + } + + addTestResult(name: string, result: string) { + this.testResults.push({ name, result }); + } + + private sendData : Uint8Array = new Uint8Array([ + 0x12, // Operation Code (INQUIRY) + 0x00, // EVPD (Vital Product Data) + 0x00, // Page Code + 0x00, // Allocation Length (high byte) + 0x24, // Allocation Length (low byte) + 0x00 // Control + ]); + + compareUint8Arrays(arr1: Uint8Array, arr2: Uint8Array): boolean { + if (arr1.length !== arr2.length) { + return false; + } + + for (let i = 0; i < arr1.length; i++) { + if (arr1[i] !== arr2[i]) { + return false; + } + } + + return true; +} + + + async runTests() { + this.testInProgress = true; + this.testResults = []; + this.progress = 0; + + if (!this.selectedDevice) { + this.addTestResult('初始化失败', '没有选择USB设备'); + this.testInProgress = false; + return; + } + + this.addTestResult('初始化成功', `USB为${this.selectedDevice.productName}`); + this.updateProgress() + // await this.testRemoveAndAddRight(); + await this.testConnectAndClaimInterface(); + this.updateProgress() + await this.testSetConfigurationAndInterface(); + this.updateProgress() + await this.testGetDescriptors(); + this.updateProgress() + await this.testDeviceInfo(); + this.updateProgress() + await this.testControlTransfers(); + this.updateProgress() + // await this.testBulkTransfers(); + // this.updateProgress() + await this.testReleaseInterface() + this.updateProgress() + await this.testSetDeviceFunctions() + this.updateProgress() + + + this.testInProgress = false; + this.end = true + } + + updateProgress(){ + const total = 8 + this.progress = this.progress + 100/total + } + + + async testRemoveAndAddRight() { + try { + // const added = usb.addRight('com.example.usbtest', this.selectedDevice.name); + // const added = usb.requestRight(this.selectedDevice.name); + // this.addTestResult('Add Right', added ? 'Success' : 'Failed'); + if(this.selectedDevice == null) return + const removed = usb.removeRight(this.selectedDevice.name); + this.addTestResult('权限移除测试', removed ? '成功' : '失败'); + } catch (error) { + this.addTestResult('增加/移除权限测试', `失败,失败原因: ${error.message}`); + } + } + + async testConnectAndClaimInterface() { + try { + this.testPipe = await usb.connectDevice(this.selectedDevice); + this.addTestResult('设备连接测试', `成功`); + + if(this.selectedDevice == null) return + + if (this.selectedDevice.configs[0] && this.selectedDevice.configs[0].interfaces[0]) { + const result = usb.claimInterface(this.testPipe, this.selectedDevice.configs[0].interfaces[0], true); + this.addTestResult('注册通信接口测试', result === 0 ? '成功' : `失败: ${result}`); + } else { + this.addTestResult('注册通信接口测试', '无法获取通讯接口'); + } + } catch (error) { + this.addTestResult('设备连接/通讯接口测试', `失败,失败原因: ${error.message}`); + } + } + + async testSetConfigurationAndInterface() { + if(this.selectedDevice == null) return + + if (!this.testPipe || !this.selectedDevice.configs[0]) return; + + try { + const configResult = usb.setConfiguration(this.testPipe, this.selectedDevice.configs[0]); + this.addTestResult('设置设备配置测试', configResult === 0 ? '成功' : `失败: ${configResult}`); + + if (this.selectedDevice.configs[0].interfaces[0]) { + const interfaceResult = usb.setInterface(this.testPipe, this.selectedDevice.configs[0].interfaces[0]); + this.addTestResult('设置设备接口测试', interfaceResult === 0 ? '成功' : `失败: ${interfaceResult}`); + } + } catch (error) { + this.addTestResult('Set Config/Interface', `Error: ${error.message}`); + } + } + + parseUsbDescriptor(rawDescriptor: Uint8Array): string { + // Here we parse the raw descriptor and extract meaningful information + // This is a simplified example and may need to be extended for full parsing + const view = new DataView(rawDescriptor.buffer); + + const deviceDescriptor: DeviceDescriptor = { + length: view.getUint8(0), + descriptorType: view.getUint8(1), + usbVersion: view.getUint16(2, true), + deviceClass: view.getUint8(4), + deviceSubClass: view.getUint8(5), + deviceProtocol: view.getUint8(6), + maxPacketSize: view.getUint8(7), + vendorId: view.getUint16(8, true), + productId: view.getUint16(10, true), + deviceVersion: view.getUint16(12, true), + manufacturer: view.getUint8(14), + product: view.getUint8(15), + serialNumber: view.getUint8(16), + numConfigurations: view.getUint8(17), + }; + + return `Length: ${deviceDescriptor.length} +Descriptor Type: ${deviceDescriptor.descriptorType} +USB Version: ${deviceDescriptor.usbVersion} +Device Class: ${deviceDescriptor.deviceClass} +Device SubClass: ${deviceDescriptor.deviceSubClass} +Device Protocol: ${deviceDescriptor.deviceProtocol} +Max Packet Size: ${deviceDescriptor.maxPacketSize} +Vendor ID: ${deviceDescriptor.vendorId} +Product ID: ${deviceDescriptor.productId} +Device Version: ${deviceDescriptor.deviceVersion} +Manufacturer Index: ${deviceDescriptor.manufacturer} +Product Index: ${deviceDescriptor.product} +Serial Number Index: ${deviceDescriptor.serialNumber} +Configuration num: ${deviceDescriptor.numConfigurations} + ` + } + + async testGetDescriptors() { + if (!this.testPipe) return; + + try { + const rawDescriptor = usb.getRawDescriptor(this.testPipe); + this.addTestResult('原始USB描述符获取测试', `成功: ${rawDescriptor.byteLength} bytes`); + this.addTestResult('原始USB描述符', `${rawDescriptor}`); + const parsedDescriptor = this.parseUsbDescriptor(rawDescriptor); + this.addTestResult('Device Descriptor 解析', `${parsedDescriptor}`); + // const fileDescriptor = usb.getFileDescriptor(this.testPipe); + // if (fileDescriptor == -1){ + // this.addTestResult('获取文件描述符测试', `失败, 文件描述符为 ${fileDescriptor}`); + // }else{ + // this.addTestResult('获取文件描述符测试', `成功, 文件描述符为 ${fileDescriptor}`); + // } + } catch (error) { + this.addTestResult('获取文件描述符测试', `失败,失败原因: ${error.message}`); + } + } + + async testDeviceInfo() { + if (this.selectedDevice == null) return; + + try { + const deviceInfo = `设备名称: ${this.selectedDevice.name} +制造商: ${this.selectedDevice.manufacturerName} +产品名: ${this.selectedDevice.productName} +设备版本: ${this.selectedDevice.version} +总线号: ${this.selectedDevice.busNum} +设备地址: ${this.selectedDevice.devAddress} +供应商ID: ${this.selectedDevice.vendorId} +产品ID: ${this.selectedDevice.productId} +类: ${this.selectedDevice.clazz} +子类: ${this.selectedDevice.subClass} +协议: ${this.selectedDevice.protocol}`; + this.addTestResult('API设备信息获取', deviceInfo); + } catch (error) { + this.addTestResult('设备信息获取失败', `失败原因: ${error.message}`); + } + } + + async testControlTransfers() { + if(this.selectedDevice == null) return; + if (!this.testPipe || !this.selectedDevice.configs[0] || !this.selectedDevice.configs[0].interfaces[0]) return; + + try { + let controlParam: usb.USBControlParams = { + request: 6, // GET_DESCRIPTOR + reqType: 0x80, // Standard request + target: 0, // Device + value: (1 << 8), // Descriptor type (1 for device descriptor) in the high byte + index: 0, // Index (0 for device descriptor) + data: new Uint8Array(18) // Buffer to receive 18 bytes of the device descriptor + }; + + usb.controlTransfer(this.testPipe, controlParam).then((ret: number) => { + console.log(`controlTransfer = ${ret}`); + this.addTestResult('控制传输测试(读取Descriptor)', `成功: ${ret} bytes`); + this.addTestResult('控制传输读取数据', `${controlParam.data}`); + const newParsedDescriptor = this.parseUsbDescriptor(controlParam.data); + this.addTestResult('控制传输读取数据解析', `${newParsedDescriptor}`); + }) + } catch (error) { + this.addTestResult('传输测试', `失败,失败原因: ${error.message}`); + } + } + + + + async performWriteBulkTransfer(pipe:usb.USBDevicePipe, endpoint: usb.USBEndpoint) { + try { + + // Perform the bulk transfer to read data from the USB disk + const bytesRead: number = await usb.bulkTransfer(pipe, endpoint, this.sendData); + + if (bytesRead !== -1) { + this.addTestResult('批量传输测试写入', `成功: ${bytesRead} bytes, 写入data为 SCSI INQUIRY command \n ${this.sendData}`); + console.log(`Write ${bytesRead} bytes successfully.`); + } else { + console.log("Bulk transfer failed."); + } + } catch (error) { + console.error("An unexpected error occurred:", error); + } + } + + + async performReadBulkTransfer(pipe:usb.USBDevicePipe, endpoint: usb.USBEndpoint) { + try { + const buffer = new Uint8Array(36); + + const bytesWritten : number = await usb.bulkTransfer(pipe, endpoint, buffer); + + if (bytesWritten !== -1) { + console.log(`Read ${bytesWritten} bytes successfully, ${buffer}`); + let flag = this.compareUint8Arrays(buffer, this.bulkResult) + if (flag){ + this.addTestResult('批量传输测试读出', `成功: ${bytesWritten} bytes,读出数据与预期一致`); + }else{ + this.addTestResult('批量传输测试读出', `失败: ${bytesWritten} bytes,读出数据与预期不匹配. 读出结果:${buffer}, 预期结果: ${this.bulkResult}`); + } + console.log(`读出数据为: ${buffer}`) + } else { + console.log("Bulk transfer failed."); + } + + } catch (error) { + console.error("An unexpected error occurred:", error); + } +} + + async testBulkTransfers() { + if (this.selectedDevice == null) return; + if (!this.testPipe || !this.selectedDevice.configs[0] || !this.selectedDevice.configs[0].interfaces[0]) return; + if (this.testPipe == null) return; + + try { + if (this.selectedDevice.configs[0].interfaces[0].endpoints[0]) { + this.performWriteBulkTransfer(this.testPipe, this.selectedDevice.configs[0].interfaces[0].endpoints[1]); + // this.performReadBulkTransfer(this.testPipe, this.selectedDevice.configs[0].interfaces[0].endpoints[1]); + this.performReadBulkTransfer(this.testPipe, this.selectedDevice.configs[0].interfaces[0].endpoints[0]); + this.performReadBulkTransfer(this.testPipe, this.selectedDevice.configs[0].interfaces[0].endpoints[0]); + // this.performReadBulkTransfer(this.testPipe, this.selectedDevice.configs[0].interfaces[0].endpoints[0]); + // this.performReadBulkTransfer(this.testPipe, this.selectedDevice.configs[0].interfaces[0].endpoints[0]); + } + } catch (error) { + this.addTestResult('传输测试', `失败,失败原因: ${error.message}`); + } + } + + async testReleaseInterface(){ + if (this.testPipe == null) return; + // if (!this.testPipe || !this.selectedDevice.configs[0] || !this.selectedDevice.configs[0].interfaces[0]) return; + if (this.selectedDevice == null) return; + + try{ + let result : number = usb.releaseInterface(this.testPipe, this.selectedDevice.configs[0].interfaces[0]) + if (result == 0){ + this.addTestResult('接口释放测试', `成功`); + }else{ + this.addTestResult('接口释放测试', `失败,失败返回值为${result}`); + } + } catch (error ){ + this.addTestResult('接口释放测试', `失败,失败原因: ${error.message}`); + } + + } + + getCurrentFunctions(store: FunctionType): string{ + switch(store){ + case 0: return "None"; + case 1: return "ACM"; + case 2: return "ECM"; + case 4: return "HDC"; + case 8: return "MTP"; + case 16: return "PTP"; + case 32: return "RNDIS"; + case 64: return "MIDI"; + case 128: return "AUDIO_SOURCE"; + case 256: return "NCM"; + default: return "未知"; + } + } + + async testSetDeviceFunctions() { + if (!this.selectedDevice) { + this.addTestResult('设置设备功能测试', '未选择设备'); + return; + } + + try { + // Define the sequence of functions to test + const functionSequence: FunctionType[] = [ + FunctionType.NONE, + FunctionType.ACM, + FunctionType.ECM, + FunctionType.MTP, + FunctionType.PTP, + FunctionType.RNDIS, + FunctionType.HDC, + ]; + + for (const func of functionSequence) { + await usb.setDeviceFunctions(func); + const currentFunctions = usb.getDeviceFunctions(); + + if (currentFunctions === func) { + this.addTestResult(`设置设备功能为 ${this.getCurrentFunctions(func)}`, '成功'); + } else { + this.addTestResult(`设置设备功能为 ${this.getCurrentFunctions(func)}`, '失败'); + } + } + } catch (error) { + this.addTestResult('设置设备功能测试', `失败,失败原因: ${error.message}`); + } + } + + // async testFunctionConversions() { + // try { + // const funcNum = usb.usbFunctionsFromString('mtp'); + // this.addTestResult('Functions From String', `Success: ${funcNum}`); + // + // const funcString = usb.usbFunctionsToString(funcNum); + // this.addTestResult('Functions To String', `Success: ${funcString}`); + // } catch (error) { + // this.addTestResult('Function Conversions', `Error: ${error.message}`); + // } + // } + // + // async testCurrentFunctions() { + // try { + // const currentFunctions = usb.getCurrentFunctions(); + // this.addTestResult('Get Current Functions', `Success: ${currentFunctions}`); + // + // await usb.setCurrentFunctions(usb.FunctionType.FUNCTION_MTP); + // this.addTestResult('Set Current Functions', 'Success'); + // } catch (error) { + // this.addTestResult('Current Functions', `Error: ${error.message}`); + // } + // } + // + // async testPortOperations() { + // try { + // const ports = usb.getPorts(); + // this.addTestResult('Get Ports', `Success: ${ports.length} ports`); + // + // if (ports.length > 0) { + // const supportedModes = usb.getSupportedModes(ports[0].id); + // this.addTestResult('Get Supported Modes', `Success: ${supportedModes}`); + // + // await usb.setPortRoles(ports[0].id, usb.PowerRoleType.SOURCE, usb.DataRoleType.HOST); + // this.addTestResult('Set Port Roles', 'Success'); + // } + // } catch (error) { + // this.addTestResult('Port Operations', `Error: ${error.message}`); + // } + // } + + build() { + Column() { + Image($r('app.media.back')) + .width(18) + .height(18) + .onClick(() => { + this.reset() + this.showDeviceSelection = true + router.back() + }) + .alignSelf(ItemAlign.Start) + + + Text('USB自动化接口测试') + .fontSize(24) + .fontWeight(FontWeight.Bold) + .textAlign(TextAlign.Center) + .margin({ bottom: 20 }) + + if (this.showDeviceSelection) { + Button('刷新设备列表') + .onClick(() => this.refreshDevices()) + .margin({ bottom: 40 }) + + if(this.devices.length !== 0){ + Text('选择一个设备进行测试:') + .fontSize(18) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 10 }) + } + + List() { + ForEach(this.devices, (device: usb.USBDevice) => { + ListItem() { + Button(){ + Column() { + Text(`设备名称: ${device.productName}`) + .fontSize(16) + .padding(5); + Text(`供应商ID: ${device.vendorId}`) + .fontSize(16) + .padding(5); + Text(`产品ID: ${device.productId}`) + .fontSize(16) + .padding(5); + } + .alignItems(HorizontalAlign.Center) + .onClick(() => { + this.selectedDevice = device; + this.showDeviceSelection = false; + promptAction.showToast({ message: `已选择设备: ${device.productName}` }); + }) + .padding(10) + .margin({ bottom: 10 }); + } + .backgroundColor(this.selectedDevice === device ? Color.Gray : Color.White) + } + }) + } + .width('100%') + .height('40%') + .margin({ bottom: 20 }) + } else { + Button('返回设备选择') + .onClick(() => { + this.reset() + this.showDeviceSelection = true; + }) + .margin({ bottom: 20 }) + } + + if (!this.showDeviceSelection && !this.end && !this.testInProgress) { + Button('开始测试') + .onClick(() => this.runTests()) + .enabled(!this.testInProgress && !!this.selectedDevice) + .margin({ bottom: 20 }) + + } + + if(!this.showDeviceSelection && this.testInProgress){ + Progress({ + value: this.progress, + }).margin({ bottom: 20 }); + } + + + List() { + ForEach(this.testResults, (result: TestResult) => { + ListItem() { + Row() { + Text(result.name) + .width('50%') + Text(result.result) + .width('50%') + } + .padding(10) + .backgroundColor(Color.White) + } + }) + } + .width('100%') + .height('80%') + } + .width('100%') + .height('100%') + .padding(20) + } +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/manual_test.ets b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/manual_test.ets new file mode 100644 index 0000000000000000000000000000000000000000..99897fa70e15bf9c1cfa7c9d677951e0eebf1622 --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/manual_test.ets @@ -0,0 +1,337 @@ +import router from '@ohos.router'; +import usbManager from '@ohos.usbManager'; +import promptAction from '@ohos.promptAction'; + + +enum PowerRoleType { + NONE = 0, + SOURCE = 1, + SINK = 2 +} + +enum DataRoleType { + NONE = 0, + HOST = 1, + DEVICE = 2 +} + +enum FunctionType { + NONE = 0, + ACM = 1, + ECM = 2, + HDC = 4, + MTP = 8, + PTP = 16, + RNDIS = 32, + MIDI = 64, + AUDIO_SOURCE = 128, + NCM = 256 +} + +@Entry +@Component +struct Results { + @State ports: Array = [] + @State functions: string = "none" + @State selectedPowerRole: PowerRoleType = PowerRoleType.NONE + @State selectedDataRole: DataRoleType = DataRoleType.NONE + @State dataRoleText: string = '无' + @State dataRoleIndex: number = 0 + @State selectedFunction: FunctionType = FunctionType.NONE + @State functionText: string = '无' + + onPageShow(): void { + this.fetchPortData() + } + + fetchPortData() { + try { + this.ports = usbManager.getPortList(); + this.functions = this.getCurrentFunctions(this.getDeviceFunctions()) + console.log("获取端口数据成功"); + } catch (error) { + console.log("获取 USB 端口数据时出错: ", error); + } + } + + getModeType(mode: usbManager.PortModeType): string { + switch (mode) { + case 0: return '无'; + case 1: return '上行端口'; + case 2: return '下行端口'; + case 3: return '动态重新配置端口'; + default: return '未知'; + } + } + + getCurrentMode(mode: number): string { + switch (mode) { + case 0: return '无'; + case 1: return 'DFP (下行端口)'; + case 2: return 'UFP (上行端口)'; + case 3: return '独立端口'; + default: return '未知'; + } + } + + getCurrentPowerRole(role: number): string { + switch (role) { + case 0: return '无'; + case 1: return '自我供电'; + case 2: return '外部供电'; + default: return '未知'; + } + } + + getCurrentFunctions(store: FunctionType): string{ + switch(store){ + case 0: return "None"; + case 1: return "ACM"; + case 2: return "ECM"; + case 4: return "HDC"; + case 8: return "MTP"; + case 16: return "PTP"; + case 32: return "RNDIS"; + case 64: return "MIDI"; + case 128: return "AUDIO_SOURCE"; + case 256: return "NCM"; + default: return "未知"; + } + } + + getCurrentDataRole(role: number): string { + switch (role) { + case 0: return '无'; + case 1: return '主机'; + case 2: return '设备'; + default: return '未知'; + } + } + + + async setPortRoleTypes(portId: number, powerRole: PowerRoleType, dataRole: DataRoleType): Promise { + try { + await usbManager.setPortRoleTypes(portId, powerRole, dataRole); + console.log(`设置端口角色成功: 端口ID = ${portId}, 电源角色 = ${powerRole}, 数据角色 = ${dataRole}`); + this.fetchPortData(); // 更新端口数据 + } catch (error) { + promptAction.showToast({ message: `${error}` }) + console.log("设置端口角色时出错: ", error); + } + } + + getDeviceFunctions(): FunctionType { + try { + const functions = usbManager.getDeviceFunctions(); + console.log(`获取当前USB功能成功: ${this.getCurrentFunctions(functions)}`); + return functions; + } catch (error) { + return FunctionType.NONE + console.log("获取当前USB功能时出错: ", error); + } + } + + async setDeviceFunctions(funcs: FunctionType): Promise { + try { + await usbManager.setDeviceFunctions(funcs); + this.fetchPortData(); + console.log(`设置当前USB功能成功: ${funcs}`); + promptAction.showToast({message:`设置当前USB功能为 ${this.getCurrentFunctions(funcs)} 成功`}) + } catch (error) { + console.log("设置当前USB功能时出错: ", error); + } + } + + build() { + Column() { + Image($r('app.media.back')) + .width(23) + .height(23) + .onClick(() => router.back()) + .alignSelf(ItemAlign.Start) + + Text('USB 端口信息') + .fontSize(24) + .fontWeight(FontWeight.Bold) + .textAlign(TextAlign.Center) + .fontColor('#ff000000') + .margin({ bottom: '20px' }) + + Button('获取端口信息') + .onClick(() => { + this.fetchPortData(); + }) + .margin({ bottom: 20 }) + + + ForEach(this.ports, (port: usbManager.USBPort) => { + Column() { + Row() { + Text('端口 ID:') + .fontSize(18) + .fontWeight(FontWeight.Bold) + .margin({ right: '15px' }) + Text(`${port.id}`) + .fontSize(18) + } + .margin({ bottom: '10px' }) + + Row() { + Text('支持的模式:') + .fontSize(18) + .fontWeight(FontWeight.Bold) + .margin({ right: '15px' }) + Text(`${this.getModeType(port.supportedModes)}`) + .fontSize(18) + } + .margin({ bottom: '20px' }) + + Row() { + Text('当前模式:') + .fontSize(18) + .fontWeight(FontWeight.Bold) + .margin({ right: '15px' }) + Text(`${this.getCurrentMode(port.status.currentMode)}`) + .fontSize(18) + } + .margin({ bottom: '20px' }) + + Row() { + Text('当前电源角色:') + .fontSize(18) + .fontWeight(FontWeight.Bold) + .margin({ right: '15px' }) + Text(`${this.getCurrentPowerRole(port.status.currentPowerRole)}`) + .fontSize(18) + } + .margin({ bottom: '20px' }) + + Row() { + Text('当前数据角色:') + .fontSize(18) + .fontWeight(FontWeight.Bold) + .margin({ right: '15px' }) + Text(`${this.getCurrentDataRole(port.status.currentDataRole)}`) + .fontSize(18) + } + .margin({ bottom: '20px' }) + + Row() { + Text('当前功能:') + .fontSize(18) + .fontWeight(FontWeight.Bold) + .margin({ right: '15px' }) + Text(`${this.functions}`) + .fontSize(18) + } + .margin({ bottom: '20px' }) + .padding({ top: '10px', bottom: '10px', left: '10px', right: '10px' }) + .backgroundColor('#ffffffff') + .borderRadius('10px') + .margin({ bottom: '60px' }) + } + }) + + Column() { + + Row() { + Text('选择数据角色:') + .fontSize(18) + .fontWeight(FontWeight.Normal) + .margin({ right: '10px' }) + Select([ + { value: '无', icon: "/common/public_icon.svg" }, + { value: '主机', icon: "/common/public_icon.svg" }, + { value: '设备', icon: "/common/public_icon.svg" } + ]) + .selected(this.dataRoleIndex) + .value(this.dataRoleText) + .font({ size: 16, weight: 500 }) + .fontColor('#182431') + .selectedOptionFont({ size: 16, weight: 400 }) + .optionFont({ size: 16, weight: 400 }) + .space(8) + .arrowPosition(ArrowPosition.END) + .menuAlign(MenuAlignType.START, { dx: 0, dy: 0 }) + .onSelect((index: number, text?: string | undefined) => { + console.info('Select DataRole:' + index) + this.dataRoleIndex = index; + if (text) { + this.dataRoleText = text; + this.selectedDataRole = index as DataRoleType; + if (index == DataRoleType.HOST){ + this.selectedPowerRole = PowerRoleType.SOURCE + }else if(index == DataRoleType.DEVICE){ + this.selectedPowerRole = PowerRoleType.SINK + }else{ + promptAction.showToast({message:`Cannot select None`}) + } + } + }) + } + .margin({ bottom: '15px' }) + + Button('设置端口角色') + .onClick(() => { + this.setPortRoleTypes( + this.ports[0].id, + this.selectedPowerRole, + this.selectedDataRole + ); + }) + .margin({ bottom: '25px' }) + + + Row() { + Text('选择设备功能:') + .fontSize(18) + .fontWeight(FontWeight.Normal) + .margin({ right: '10px' }) + Select([ + { value: '无', icon: "/common/public_icon.svg" }, + { value: 'ACM', icon: "/common/public_icon.svg" }, + { value: 'ECM', icon: "/common/public_icon.svg" }, + { value: 'HDC', icon: "/common/public_icon.svg" }, + { value: 'MTP', icon: "/common/public_icon.svg" }, + { value: 'PTP', icon: "/common/public_icon.svg" }, + { value: 'RNDIS', icon: "/common/public_icon.svg" }, + { value: 'MIDI', icon: "/common/public_icon.svg" }, + { value: 'AUDIO_SOURCE', icon: "/common/public_icon.svg" }, + { value: 'NCM', icon: "/common/public_icon.svg" } + ]) + .selected(0) + .value(this.functionText) + .font({ size: 16, weight: 500 }) + .fontColor('#182431') + .selectedOptionFont({ size: 16, weight: 400 }) + .optionFont({ size: 16, weight: 400 }) + .space(8) + .arrowPosition(ArrowPosition.END) + .menuAlign(MenuAlignType.START, { dx: 0, dy: 0 }) + .onSelect((index: number, text?: string | undefined) => { + console.info('Select Function:' + index) + if (index === 0){ + this.selectedFunction = 0 + }else{ + this.selectedFunction = 1 << (index - 1); + } + if (text) { + this.functionText = text; + } + }) + } + .margin({ bottom: '15px' }) + + Button('设置设备功能') + .onClick(() => { + this.setDeviceFunctions(this.selectedFunction); + }) + .margin({ bottom: '25px' }) + } + } + .width('100%') + .height('100%') + .padding({ top: '20px', bottom: '20px', left: '10px', right: '10px' }) + .backgroundColor('#ffffffff') + } +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/split_test.ets b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/split_test.ets new file mode 100644 index 0000000000000000000000000000000000000000..00c83835f8c8290a289e04f977048d5d18afdb17 --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/split_test.ets @@ -0,0 +1,264 @@ +import usb from "@ohos.usbManager"; +import promptAction from '@ohos.promptAction'; +import router from '@ohos.router'; + +@Entry +@Component +struct UsbTestPage { + @State devices: Array = []; + @State selectedDevice: usb.USBDevice | null = null; + @State devicePipe: usb.USBDevicePipe | null = null; + @State output: string = ''; + @State expandedInterface: number | null = null; // Track which interface is expanded + + aboutToAppear() { + this.refreshDevices(); + } + + refreshDevices() { + let devicesList: Array = usb.getDevices(); + if (devicesList.length == 0) { + console.warn("no device is connected"); + promptAction.showToast({ message: '没有找到USB设备' }); + this.devices = []; + } else { + this.devices = devicesList; + } + } + + connectDevice(device: usb.USBDevice) { + try { + let pipe = usb.connectDevice(device); + this.devicePipe = pipe; + this.output = `已连接到设备: ${device.name}`; + } catch (error) { + this.output = `连接设备失败: ${error.message}`; + } + } + + claimInterface(pipe: usb.USBDevicePipe, iface: usb.USBInterface) { + try { + let result = usb.claimInterface(pipe, iface, true); + if (result < 0) { + this.output = `通信接口注册失败(claimInterface): ${result}`; + } else { + this.output = `通信接口已注册(claimInterface): ${result}`; + } + + } catch (error) { + this.output = `通信接口注册失败(claimInterface): ${error.message}`; + } + } + + releaseInterface(pipe: usb.USBDevicePipe, iface: usb.USBInterface) { + try { + let result = usb.releaseInterface(pipe, iface); + this.output = `通信接口释放成功(releaseInterface): ${result}`; + } catch (error) { + this.output = `通信接口释放失败(releaseInterface): ${error.message}`; + } + } + + setInterface(pipe: usb.USBDevicePipe, iface: usb.USBInterface) { + try { + let result = usb.setInterface(pipe, iface); + this.output = `设置设备接口成功(setInterface): ${result}`; + } catch (error) { + this.output = `设置设备接口失败(setInterface): ${error.message}`; + } + } + + closePipe(pipe: usb.USBDevicePipe) { + try { + let result = usb.closePipe(pipe); + this.output = `关闭设备消息控制通道成功(closePipe): ${result}`; + this.devicePipe = null; + } catch (error) { + this.output = `关闭设备消息控制通道失败(closePipe): ${error.message}`; + } + } + + setConfiguration(pipe: usb.USBDevicePipe, config: usb.USBConfiguration) { + try { + let result = usb.setConfiguration(pipe, config); + this.output = `设置设备配置成功(setConfiguration): ${result}`; + } catch (error) { + this.output = `设置设备配置失败(setConfiguration): ${error.message}`; + } + } + + getInterfaces(): Array { + if (this.selectedDevice && this.selectedDevice.configs.length > 0) { + return this.selectedDevice.configs[0].interfaces; // Assuming the first config + } + return []; + } + + toggleInterface(index: number) { + if (this.expandedInterface === index) { + this.expandedInterface = null; + } else { + this.expandedInterface = index; + } + } + + build() { + Column() { + Image($r('app.media.back')) + .width(18) + .height(18) + .onClick(() => router.back()) + .alignSelf(ItemAlign.Start) + + Text('USB接口分离测试') + .fontSize(24) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 20 }) + + if (!this.selectedDevice) { + Button('刷新设备列表') + .onClick(() => { + this.refreshDevices(); + }) + .margin({ bottom: 20 }) + .width('100%') + + Scroll() { + List() { + ForEach(this.devices, (device: usb.USBDevice, index) => { + ListItem() { + Row() { + Column() { + Text(`设备名称: ${device.name}`) + Text(`制造商: ${device.manufacturerName}`) + Text(`产品名: ${device.productName}`) + Text(`版本: ${device.version}`) + } + .layoutWeight(1) + + Radio({ value: index.toString(), group: 'devices' }) + .onChange((isChecked: boolean) => { + if (isChecked) { + this.selectedDevice = device; + promptAction.showToast({ message: `已选择设备: ${device.productName}` }); + } + }) + } + .width('100%') + .padding(10) + .backgroundColor(this.selectedDevice === device ? Color.Gray : Color.White) + } + }) + } + .width('100%') + .height('50%') + } + } else { + Scroll() { + Column() { + + Text(`设备名称: ${this.selectedDevice?.name}`) + .fontSize(20) + .fontWeight(FontWeight.Bold) + .margin({ top: 20, bottom: 10 }) + + Text(`制造商: ${this.selectedDevice?.manufacturerName}`) + .fontSize(20) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 20 }) + + Button('连接设备') + .onClick(() => { + if (this.selectedDevice) { + this.connectDevice(this.selectedDevice); + } + }) + .margin({ bottom: 10 }) + .width('100%') + + if (this.devicePipe) { + ForEach(this.getInterfaces(), (iface: usb.USBInterface, index) => { + Column() { + Button(`Interface ${index + 1}`) + .onClick(() => { + this.toggleInterface(index); + }) + .margin({ bottom: 10 }) + .width('100%') + + if (this.expandedInterface === index) { + Column() { + Button(`注册通信接口`) + .onClick(() => { + if (this.devicePipe) { + this.claimInterface(this.devicePipe, iface); + } + }) + .margin({ bottom: 10 }) + .width('100%') + .backgroundColor(Color.Grey) // Different color for sub-buttons + + Button(`设置设备接口`) + .onClick(() => { + if (this.devicePipe) { + this.setInterface(this.devicePipe, iface); + } + }) + .margin({ bottom: 10 }) + .width('100%') + .backgroundColor(Color.Grey) // Different color for sub-buttons + + Button(`释放通信接口`) + .onClick(() => { + if (this.devicePipe) { + this.releaseInterface(this.devicePipe, iface); + } + }) + .margin({ bottom: 10 }) + .width('100%') + .backgroundColor(Color.Grey) // Different color for sub-buttons + + } + .margin({ left: 20 }) + } + } + .width('100%') + }) + + ForEach(this.selectedDevice?.configs, (config: usb.USBConfiguration, index) => { + Column() { + Button(`设置设备配置`) + .onClick(() => { + if (this.devicePipe) { + this.setConfiguration(this.devicePipe, config); + } + }) + .margin({ bottom: 10 }) + .width('100%') + } + .width('100%') + }) + + Button('关闭设备消息控制通道') + .onClick(() => { + if (this.devicePipe) { + this.closePipe(this.devicePipe); + } + }) + .margin({ bottom: 10 }) + .width('100%') + } + } + .width('100%') + } + } + + Text(this.output) + .fontSize(18) + .margin({ top: 20 }) + } + .width('100%') + .height('100%') + .padding(20) + } +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/usb_info.ets b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/usb_info.ets new file mode 100644 index 0000000000000000000000000000000000000000..1a9c5c8db5fe6ae89916275d249b8f7aaee79bdf --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/usb_info.ets @@ -0,0 +1,151 @@ +import usb from "@ohos.usbManager"; +import promptAction from '@ohos.promptAction'; +import router from '@ohos.router'; + +@Entry +@Component +struct UsbInfoPage { + @State devices: Array = []; + @State selectedDevice: usb.USBDevice | null = null; + @State deviceRights: Map = new Map(); + + aboutToAppear() { + this.refreshDevices(); + } + + refreshDevices() { + let devicesList: Array = usb.getDevices(); + if (devicesList.length == 0) { + console.warn("no device is connected") + promptAction.showToast({ message: '没有找到USB设备' }) + this.devices = [] + } else { + this.devices = devicesList + this.updateDeviceRights(); + } + } + + updateDeviceRights() { + this.deviceRights.clear(); + this.devices.forEach(device => { + let right: boolean = usb.hasRight(device.name) + this.deviceRights.set(device.name, right); + }); + } + + removeRight(deviceName: string): boolean { + try { + usb.removeRight(deviceName); + return true; + } catch (error) { + promptAction.showToast({ message: `权限移除失败: ${error.message}` }); + return false; + } + } + + build() { + Column() { + Image($r('app.media.back')) + .width(18) + .height(18) + .onClick(() => router.back()) + .alignSelf(ItemAlign.Start) + + Text('USB设备信息') + .fontSize(24) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 20 }) + + Button('刷新设备列表') + .onClick(() => { + this.refreshDevices(); + }) + .margin({ bottom: 20 }) + + Scroll() { + Column() { + ForEach(this.devices, (device: usb.USBDevice, index) => { + ListItem() { + Button() { + Column() { + Text(`设备名称: ${device.name}`) + Text(`制造商: ${device.manufacturerName}`) + Text(`产品名: ${device.productName}`) + Text(`版本: ${device.version}`) + Text(`总线号: ${device.busNum}`) + Text(`设备地址: ${device.devAddress}`) + Text(`序列号: ${device.serial}`) + Text(`厂商ID: ${device.vendorId}`) + Text(`产品ID: ${device.productId}`) + Text(`类: ${device.clazz}`) + Text(`子类: ${device.subClass}`) + Text(`协议: ${device.protocol}`) + Text(`是否有权限访问: ${this.deviceRights.get(device.name) ? '是' : '否'}`) + } + .padding(10) + } + .backgroundColor(this.selectedDevice === device ? Color.Gray : Color.White) + .borderRadius(0) // Make the corners square + .onClick(() => { + this.selectedDevice = device; + promptAction.showToast({ message: `Selected device: ${device.productName}`, bottom:"120vp" }) + }) + .padding(10) + } + .width('100%') + }) + } + .width('100%') + } + .width('100%') + .height('70%') + + if (this.selectedDevice) { + Column() { + Text('选中设备操作') + .fontSize(20) + .fontWeight(FontWeight.Bold) + .margin({ top: 20, bottom: 20 }) + + Row() { + Button('请求权限', { type: ButtonType.Capsule, stateEffect: true }) + .onClick(() => { + if (this.selectedDevice == null) return + usb.requestRight(this.selectedDevice.name) + .then((hasRight) => { + if (hasRight) { + promptAction.showToast({ message: '权限请求成功', bottom:"120vp" }); + this.updateDeviceRights(); + } else { + promptAction.showToast({ message: '权限被拒绝', bottom:"120vp" }); + } + }) + .catch((error: Error) => { + promptAction.showToast({ message: `权限请求失败: ${error.message}`, bottom:"120vp" }); + }); + }) + .margin({ right: 20 }) + + Button('移除权限', { type: ButtonType.Capsule, stateEffect: false }) + .onClick(() => { + if (this.selectedDevice == null) return + let result = this.removeRight(this.selectedDevice.name); + if (result) { + promptAction.showToast({ message: '权限移除成功', bottom:"120vp" }); + this.updateDeviceRights(); + } + }) + .margin({ left: 20 }) + } + .justifyContent(FlexAlign.Center) + .width('100%') + .margin({ bottom: 10 }) + } + .width('100%') + } + } + .width('100%') + .height('100%') + .padding(20) + } +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/usb_listening.ets b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/usb_listening.ets new file mode 100644 index 0000000000000000000000000000000000000000..4f30b5ec4bd3a49089d25fc67a94473ef15dadc4 --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/pages/usb_listening.ets @@ -0,0 +1,280 @@ +import promptAction from '@ohos.promptAction'; +import commonEvent from '@ohos.commonEventManager'; +import router from '@ohos.router'; + +// Define interfaces and types +interface Endpoint { + address: number; + attributes: number; + interval: number; + maxPacketSize: number; + direction: number; + number: number; + type: number; + interfaceId: number; +} + +interface UsbInterface { + id: number; + protocol: number; + clazz: number; + subClass: number; + alternateSetting: number; + name: string; + endpoints: Endpoint[]; +} + +interface UsbConfig { + id: number; + attributes: number; + maxPower: number; + name: string; + isRemoteWakeup: boolean; + isSelfPowered: boolean; + interfaces: UsbInterface[]; +} + +interface UsbDeviceEventData { + busNum: number; + devAddress: number; + serial: string; + name: string; + manufacturerName: string; + productName: string; + version: string; + vendorId: number; + productId: number; + clazz: number; + subClass: number; + protocol: number; + configs: UsbConfig[]; +} + +interface USBDeviceInfo { + productName: string; + manufacturerName: string; +} + +interface SubscriberInfo { + events: string[]; +} + +@Entry +@Component +struct UsbEventPage { + @State deviceInfo: USBDeviceInfo | null = null; + @State isListening: boolean = false; + @State eventData: string | null = null; // Used to store event data string + @State usbDeviceCount: number = 0; // Count of connected USB devices + private usbSubscriber: commonEvent.CommonEventSubscriber | null = null; + + aboutToAppear() { + } + + aboutToDisappear() { + this.stopUsbListening(); + } + + toggleUsbEvents() { + if (this.isListening) { + this.stopUsbListening(); + this.usbDeviceCount = 0 + this.eventData = null + this.deviceInfo = null + } else { + this.startUsbListening(); + } + this.isListening = !this.isListening; + } + + startUsbListening() { + const subscriberInfo: SubscriberInfo = { + events: [ + 'usual.event.hardware.usb.action.USB_DEVICE_ATTACHED', + 'usual.event.hardware.usb.action.USB_DEVICE_DETACHED' + ] + }; + + commonEvent.createSubscriber(subscriberInfo, (err, subscriber) => { + if (err) { + promptAction.showToast({ message: `创建订阅者失败: ${err.message}` }); + return; + } + + this.usbSubscriber = subscriber; + + commonEvent.subscribe(this.usbSubscriber, (err, event) => { + if (err) { + promptAction.showToast({ message: `订阅事件失败: ${err.message}` }); + return; + } + + if (event.event === 'usual.event.hardware.usb.action.USB_DEVICE_ATTACHED') { + this.handleUsbDeviceAdd(event); + } else if (event.event === 'usual.event.hardware.usb.action.USB_DEVICE_DETACHED') { + this.handleUsbDeviceRemove(event); + } + }); + }); + } + + handleUsbDeviceAdd(event: commonEvent.CommonEventData) { + if (event.data) { + try { + const deviceData: UsbDeviceEventData = JSON.parse(event.data); + this.deviceInfo = { + productName: deviceData.productName, + manufacturerName: deviceData.manufacturerName + }; + this.eventData = this.formatEventData(deviceData); + this.usbDeviceCount++; // Increment device count + promptAction.showToast({ message: `设备已插入: ${deviceData.productName}` }); + } catch (error) { + this.eventData = '解析设备数据失败'; + promptAction.showToast({ message: '解析设备数据失败' }); + } + } else { + this.eventData = '事件数据为空'; + promptAction.showToast({ message: '事件数据为空' }); + } + } + + handleUsbDeviceRemove(event: commonEvent.CommonEventData) { + if (this.deviceInfo !== null) { + promptAction.showToast({ message: `设备已拔出: ${this.deviceInfo.productName}` }); + this.deviceInfo = null; + if (this.usbDeviceCount > 0) { + this.usbDeviceCount--; // Decrement device count + } + } + } + + stopUsbListening() { + if (this.usbSubscriber !== null) { + commonEvent.unsubscribe(this.usbSubscriber, (err) => { + if (err) { + promptAction.showToast({ message: `取消订阅失败: ${err.message}` }); + } + }); + this.usbSubscriber = null; + } + } + + formatEventData(deviceData: UsbDeviceEventData): string { + let formattedData = ` + 设备名称: ${deviceData.name}\n + 产品名称: ${deviceData.productName}\n + 制造商名称: ${deviceData.manufacturerName}\n + 版本: ${deviceData.version}\n + 供应商ID: ${deviceData.vendorId}\n + 产品ID: ${deviceData.productId}\n + 类别: ${deviceData.clazz}\n + 子类别: ${deviceData.subClass}\n + 协议: ${deviceData.protocol}\n + 总线编号: ${deviceData.busNum}\n + 设备地址: ${deviceData.devAddress}\n + 配置数量: ${deviceData.configs.length} + `; + + deviceData.configs.forEach((config, configIndex) => { + formattedData += `\n\n**配置 ${configIndex + 1}:**\n`; + formattedData += ` + 配置ID: ${config.id}\n + 配置名称: ${config.name}\n + 属性: ${config.attributes}\n + 最大功率: ${config.maxPower}\n + 远程唤醒: ${config.isRemoteWakeup}\n + 自供电: ${config.isSelfPowered}\n + 接口数量: ${config.interfaces.length} + `; + + config.interfaces.forEach((usbInterface, interfaceIndex) => { + formattedData += `\n **接口 ${interfaceIndex + 1}:**\n`; + formattedData += ` + 接口ID: ${usbInterface.id}\n + 接口名称: ${usbInterface.name}\n + 类别: ${usbInterface.clazz}\n + 子类别: ${usbInterface.subClass}\n + 协议: ${usbInterface.protocol}\n + 备用设置: ${usbInterface.alternateSetting}\n + 端点数量: ${usbInterface.endpoints.length} + `; + + usbInterface.endpoints.forEach((endpoint, endpointIndex) => { + formattedData += `\n **端点 ${endpointIndex + 1}:**\n`; + formattedData += ` + 地址: ${endpoint.address}\n + 属性: ${endpoint.attributes}\n + 间隔: ${endpoint.interval}\n + 最大包尺寸: ${endpoint.maxPacketSize}\n + 方向: ${endpoint.direction}\n + 编号: ${endpoint.number}\n + 类型: ${endpoint.type} + `; + }); + }); + }); + + return formattedData; + } + + build() { + Column() { + Image($r('app.media.back')) + .width(18) + .height(18) + .onClick(() => router.back()) + .alignSelf(ItemAlign.Start) + + Text('USB 插拔事件通知') + .fontSize(24) + .fontWeight(FontWeight.Bold) + .margin({ bottom: 20 }) + + Button(this.isListening ? '停止监听 USB 事件' : '开始监听 USB 事件') + .fontSize(20) + .onClick(() => this.toggleUsbEvents()) + .margin({ bottom: 20 }) + + Text(`连接的 USB 设备数量: ${this.usbDeviceCount}`) + .fontSize(15) + .margin({ bottom: 20 }) + + if (this.deviceInfo && this.isListening) { + Column() { + Text(`产品名称: ${this.deviceInfo.productName}`) + .fontSize(18) + .margin({ bottom: 10 }) + Text(`制造商名称: ${this.deviceInfo.manufacturerName}`) + .fontSize(18) + .margin({ bottom: 10 }) + } + .padding(10) + .backgroundColor(Color.White) + .borderRadius(10) + } else { + Text('没有设备连接') + .fontSize(20) + } + + if (this.eventData && this.deviceInfo && this.isListening) { + // Adding a scrollable area for event data + Scroll() { + Text(`${this.eventData}`) + .fontSize(16) + .padding(10) + .backgroundColor(Color.White) + .borderRadius(10) + } + .width('100%') + .height(500) + .margin({ top: 20 }) + .backgroundColor(Color.White) + } + } + .width('100%') + .height('100%') + .padding(20) + .backgroundColor(Color.White) + } +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/usbability/UsbAbility.ets b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/usbability/UsbAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..30bdb92438bd6c2623c54ca23d6a4f07a25ef36a --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/ets/usbability/UsbAbility.ets @@ -0,0 +1,43 @@ +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; + +export default class UsbAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/module.json5 b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..004529c642814e6fee4f9c6041f10a7a65c26de3 --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/module.json5 @@ -0,0 +1,47 @@ +{ + "module": { + "name": "usb", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "UsbAbility", + "deviceTypes": [ + "default", + "tablet", + "tv", + "wearable", + "car", + "2in1" + ], + "requestPermissions":[ + { + "name" : "ohos.permission.MANAGE_USB_CONFIG", + "reason": "$string:reason", + "usedScene": {} + }], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "UsbAbility", + "srcEntry": "./ets/usbability/UsbAbility.ets", + "description": "$string:UsbAbility_desc", + "icon": "$media:usbPort", + "label": "$string:UsbAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/element/color.json b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/element/string.json b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..debc484c60a37c5c7d327e8de46e4f109df7dc0a --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/element/string.json @@ -0,0 +1,20 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "UsbAbility_desc", + "value": "description" + }, + { + "name": "UsbAbility_label", + "value": "label" + }, + { + "name": "reason", + "value": "API use" + } + ] +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/back.png b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/back.png new file mode 100644 index 0000000000000000000000000000000000000000..455e45ef77db425500a08dc35dcf974923c044a0 Binary files /dev/null and b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/back.png differ diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/huawei.png b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/huawei.png new file mode 100644 index 0000000000000000000000000000000000000000..502a6ad204eae68fd914ec1947546507d0de5ca7 Binary files /dev/null and b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/huawei.png differ diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/icon.png b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cd45accb1dfd2fd0da16c732c72faa6e46b26521 Binary files /dev/null and b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/icon.png differ diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/startIcon.png b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..366f76459ffd4494ec40d0ddd5c59385b9c5da11 Binary files /dev/null and b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/startIcon.png differ diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/usbPort.png b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/usbPort.png new file mode 100644 index 0000000000000000000000000000000000000000..cd5d6bb9fbe2f3e035726ecc02d00ae53b02cd88 Binary files /dev/null and b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/media/usbPort.png differ diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/profile/main_pages.json b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..dfb9ee91f800239be1de7ca951704de1e3e15df8 --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,10 @@ +{ + "src": [ + "pages/Index", + "pages/automation", + "pages/usb_info", + "pages/usb_listening", + "pages/split_test", + "pages/manual_test" + ] +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/en_US/element/string.json b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..debc484c60a37c5c7d327e8de46e4f109df7dc0a --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/en_US/element/string.json @@ -0,0 +1,20 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "UsbAbility_desc", + "value": "description" + }, + { + "name": "UsbAbility_label", + "value": "label" + }, + { + "name": "reason", + "value": "API use" + } + ] +} \ No newline at end of file diff --git a/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/zh_CN/element/string.json b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..6b54056a80a951957924c713d7b7677ab694f6f9 --- /dev/null +++ b/test/native/unittest/usb.manager-test-hap-master/usb/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,20 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "UsbAbility_desc", + "value": "description" + }, + { + "name": "UsbAbility_label", + "value": "label" + }, + { + "name": "reason", + "value": "API use" + } + ] +} \ No newline at end of file