1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { Serialize } from '../common/Serialize'; 17import { HdcCommand } from './HdcCommand'; 18import { Utils } from '../common/Utils'; 19import { HANDSHAKE_MESSAGE } from '../common/ConstantType'; 20import { PayloadHead } from '../message/PayloadHead'; 21import { TransmissionInterface } from '../transmission/TransmissionInterface'; 22import { DataProcessing } from '../transmission/DataProcessing'; 23import { DataListener } from './DataListener'; 24import { DataMessage } from '../message/DataMessage'; 25import { SessionHandShake } from '../message/SessionHandShake'; 26import { AuthType } from '../message/AuthType'; 27import { debug, log } from '../../log/Log'; 28import { HdcStream } from './HdcStream'; 29import { toHex16 } from '../common/BaseConversion'; 30import { USBHead } from '../message/USBHead'; 31 32export class HdcClient implements DataListener { 33 // @ts-ignore 34 usbDevice: USBDevice | undefined; 35 sessionId: number = 0; 36 private transmissionChannel: TransmissionInterface; 37 public readDataProcessing: DataProcessing; 38 private cmdStreams = new Map(); 39 40 constructor( 41 transmissionChannel: TransmissionInterface, 42 // @ts-ignore 43 usbDevice: USBDevice | undefined 44 ) { 45 this.transmissionChannel = transmissionChannel; 46 this.usbDevice = usbDevice; 47 this.readDataProcessing = new DataProcessing(this, transmissionChannel); 48 } 49 50 async connectDevice(): Promise<boolean> { 51 debug('start Connect Device'); 52 this.sessionId = Utils.getSessionId(); 53 log(`sessionId is ${this.sessionId}`); 54 // @ts-ignore 55 let handShake: SessionHandShake = new SessionHandShake( 56 HANDSHAKE_MESSAGE, 57 AuthType.AUTH_NONE, 58 this.sessionId, 59 // @ts-ignore 60 this.usbDevice.serialNumber, 61 '' 62 ); 63 let hs = Serialize.serializeSessionHandShake(handShake); 64 debug('start Connect hs ', hs); 65 let sendResult = await this.readDataProcessing.send( 66 handShake.sessionId, 67 0, 68 HdcCommand.CMD_KERNEL_HANDSHAKE, 69 hs, 70 hs.length 71 ); 72 if (sendResult) { 73 let handShake = await this.readDataProcessing.readUsbHead(); 74 let handBody = await this.readDataProcessing.readBody(handShake!.dataSize); 75 if (this.sessionId === handShake!.sessionId) { 76 debug('handShake: ', handShake); 77 this.handShakeSuccess(handBody); 78 return true; 79 } else { 80 log(`session is not eq handShake?.sessionId is : ${handShake?.sessionId} now session is ${this.sessionId}`); 81 return false; 82 } 83 } else { 84 return false; 85 } 86 } 87 88 private handShakeSuccess(handBody: DataView): void { 89 let playHeadArray = handBody.buffer.slice(0, PayloadHead.getPayloadHeadLength()); 90 let resultPayloadHead: PayloadHead = PayloadHead.parsePlayHead(new DataView(playHeadArray)); 91 debug('resultPayloadHead is ', resultPayloadHead); 92 let headSize = resultPayloadHead.headSize; 93 let dataSize = resultPayloadHead.dataSize; 94 let resPlayProtectBuffer = handBody.buffer.slice( 95 PayloadHead.getPayloadHeadLength(), 96 PayloadHead.getPayloadHeadLength() + headSize 97 ); 98 debug('PlayProtect is ', resPlayProtectBuffer); 99 let resData = handBody.buffer.slice( 100 PayloadHead.getPayloadHeadLength() + headSize, 101 PayloadHead.getPayloadHeadLength() + headSize + dataSize 102 ); 103 debug('resData is ', resData); 104 this.readDataProcessing.startReadData().then(() => {}); 105 } 106 public async disconnect(): Promise<void> { 107 try { 108 await this.transmissionChannel.close(); 109 this.readDataProcessing.stopReadData(); 110 this.cmdStreams.forEach((value) => { 111 value.putMessageInQueue(new DataMessage(new USBHead([0, 1], -1, -1, -1))); 112 }); 113 this.cmdStreams.clear(); 114 } catch (e) {} 115 } 116 117 public bindStream(channel: number, hdcStream: HdcStream): void { 118 this.cmdStreams.set(channel, hdcStream); 119 } 120 121 public unbindStream(channel: number): boolean { 122 this.cmdStreams['delete'](channel); 123 return true; 124 } 125 126 public unbindStopStream(channel: number): boolean { 127 this.cmdStreams['delete'](channel); 128 return true; 129 } 130 131 createDataMessage(data: DataMessage): void { 132 if (this.cmdStreams.has(data.getChannelId())) { 133 let stream = this.cmdStreams.get(data.getChannelId()); 134 if (stream) { 135 stream.putMessageInQueue(data); 136 } 137 } 138 } 139} 140