1fb726d48Sopenharmony_ci/* 2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb726d48Sopenharmony_ci * You may obtain a copy of the License at 6fb726d48Sopenharmony_ci * 7fb726d48Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb726d48Sopenharmony_ci * 9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and 13fb726d48Sopenharmony_ci * limitations under the License. 14fb726d48Sopenharmony_ci */ 15fb726d48Sopenharmony_ci 16fb726d48Sopenharmony_ciimport { TransmissionInterface } from './TransmissionInterface'; 17fb726d48Sopenharmony_ciimport { info } from '../../log/Log'; 18fb726d48Sopenharmony_ciimport { HDC_DEVICE_FILTER } from '../common/ConstantType'; 19fb726d48Sopenharmony_ci 20fb726d48Sopenharmony_ciexport interface matchingUsbDevice { 21fb726d48Sopenharmony_ci configurationValue: number; 22fb726d48Sopenharmony_ci interfaceNumber: number; 23fb726d48Sopenharmony_ci // @ts-ignore 24fb726d48Sopenharmony_ci endPoints: USBEndpoint[]; 25fb726d48Sopenharmony_ci} 26fb726d48Sopenharmony_ci 27fb726d48Sopenharmony_ciexport class UsbTransmissionChannel implements TransmissionInterface { 28fb726d48Sopenharmony_ci // @ts-ignore 29fb726d48Sopenharmony_ci private _device: USBDevice | null; 30fb726d48Sopenharmony_ci private readonly endpointIn: number; 31fb726d48Sopenharmony_ci private readonly endpointOut: number; 32fb726d48Sopenharmony_ci private readonly interfaceNumber: number; 33fb726d48Sopenharmony_ci 34fb726d48Sopenharmony_ci private constructor( 35fb726d48Sopenharmony_ci // @ts-ignore 36fb726d48Sopenharmony_ci device: USBDevice, 37fb726d48Sopenharmony_ci endpointIn: number, 38fb726d48Sopenharmony_ci endpointOut: number, 39fb726d48Sopenharmony_ci interfaceNumber: number 40fb726d48Sopenharmony_ci ) { 41fb726d48Sopenharmony_ci this._device = device; 42fb726d48Sopenharmony_ci this.endpointIn = endpointIn; 43fb726d48Sopenharmony_ci this.endpointOut = endpointOut; 44fb726d48Sopenharmony_ci this.interfaceNumber = interfaceNumber; 45fb726d48Sopenharmony_ci } 46fb726d48Sopenharmony_ci 47fb726d48Sopenharmony_ci /** 48fb726d48Sopenharmony_ci * Send data to the device side 49fb726d48Sopenharmony_ci * 50fb726d48Sopenharmony_ci * @param writeData writeData 51fb726d48Sopenharmony_ci */ 52fb726d48Sopenharmony_ci async writeData(writeData: ArrayBuffer): Promise<void> { 53fb726d48Sopenharmony_ci await this._device?.transferOut(this.endpointOut, writeData); 54fb726d48Sopenharmony_ci } 55fb726d48Sopenharmony_ci 56fb726d48Sopenharmony_ci /** 57fb726d48Sopenharmony_ci * read data from device via usb 58fb726d48Sopenharmony_ci * 59fb726d48Sopenharmony_ci * @param length 60fb726d48Sopenharmony_ci */ 61fb726d48Sopenharmony_ci async readData(length: number): Promise<DataView> { 62fb726d48Sopenharmony_ci const result = await this._device?.transferIn(this.endpointOut, length); 63fb726d48Sopenharmony_ci if (result?.data) { 64fb726d48Sopenharmony_ci return result.data; 65fb726d48Sopenharmony_ci } else { 66fb726d48Sopenharmony_ci return Promise.resolve(new DataView(new ArrayBuffer(0))); 67fb726d48Sopenharmony_ci } 68fb726d48Sopenharmony_ci } 69fb726d48Sopenharmony_ci 70fb726d48Sopenharmony_ci /** 71fb726d48Sopenharmony_ci * Close the device connection 72fb726d48Sopenharmony_ci */ 73fb726d48Sopenharmony_ci async close(): Promise<void> { 74fb726d48Sopenharmony_ci try { 75fb726d48Sopenharmony_ci await this._device?.releaseInterface(this.interfaceNumber); 76fb726d48Sopenharmony_ci await this._device?.close(); 77fb726d48Sopenharmony_ci } catch (e) {} 78fb726d48Sopenharmony_ci this._device = null; 79fb726d48Sopenharmony_ci } 80fb726d48Sopenharmony_ci 81fb726d48Sopenharmony_ci /** 82fb726d48Sopenharmony_ci * 打开设备 83fb726d48Sopenharmony_ci * 84fb726d48Sopenharmony_ci * @param usbDevice 85fb726d48Sopenharmony_ci */ 86fb726d48Sopenharmony_ci static async openHdcDevice( 87fb726d48Sopenharmony_ci // @ts-ignore 88fb726d48Sopenharmony_ci usbDevice: USBDevice 89fb726d48Sopenharmony_ci ): Promise<UsbTransmissionChannel | null> { 90fb726d48Sopenharmony_ci try { 91fb726d48Sopenharmony_ci await usbDevice.open(); 92fb726d48Sopenharmony_ci const matchDevice = this.filterAndFindDevice(usbDevice, HDC_DEVICE_FILTER); 93fb726d48Sopenharmony_ci info('matchDevice is', matchDevice); 94fb726d48Sopenharmony_ci if (!matchDevice) { 95fb726d48Sopenharmony_ci throw new Error('Could not find hdc device'); 96fb726d48Sopenharmony_ci } 97fb726d48Sopenharmony_ci await usbDevice.selectConfiguration(matchDevice.configurationValue); 98fb726d48Sopenharmony_ci await usbDevice.claimInterface(matchDevice.interfaceNumber); 99fb726d48Sopenharmony_ci const endpointIn = UsbTransmissionChannel.filterEndpointNumber(matchDevice.endPoints, 'in'); 100fb726d48Sopenharmony_ci const endpointOut = UsbTransmissionChannel.filterEndpointNumber(matchDevice.endPoints, 'out'); 101fb726d48Sopenharmony_ci return new UsbTransmissionChannel(usbDevice, endpointIn, endpointOut, matchDevice.interfaceNumber); 102fb726d48Sopenharmony_ci } catch (e) { 103fb726d48Sopenharmony_ci return Promise.resolve(null); 104fb726d48Sopenharmony_ci } 105fb726d48Sopenharmony_ci } 106fb726d48Sopenharmony_ci 107fb726d48Sopenharmony_ci /** 108fb726d48Sopenharmony_ci * Filter out matching devices 109fb726d48Sopenharmony_ci * 110fb726d48Sopenharmony_ci * @param device device 111fb726d48Sopenharmony_ci * @param filter filter 112fb726d48Sopenharmony_ci */ 113fb726d48Sopenharmony_ci private static filterAndFindDevice( 114fb726d48Sopenharmony_ci // @ts-ignore 115fb726d48Sopenharmony_ci device: USBDevice, 116fb726d48Sopenharmony_ci // @ts-ignore 117fb726d48Sopenharmony_ci filter: USBDeviceFilter 118fb726d48Sopenharmony_ci ): matchingUsbDevice | null { 119fb726d48Sopenharmony_ci for (const config of device.configurations) { 120fb726d48Sopenharmony_ci for (const intf of config.interfaces) { 121fb726d48Sopenharmony_ci for (const al of intf.alternates) { 122fb726d48Sopenharmony_ci if ( 123fb726d48Sopenharmony_ci filter.classCode === al.interfaceClass && 124fb726d48Sopenharmony_ci filter.subclassCode === al.interfaceSubclass && 125fb726d48Sopenharmony_ci filter.protocolCode === al.interfaceProtocol 126fb726d48Sopenharmony_ci ) { 127fb726d48Sopenharmony_ci return { 128fb726d48Sopenharmony_ci configurationValue: config.configurationValue, 129fb726d48Sopenharmony_ci interfaceNumber: intf.interfaceNumber, 130fb726d48Sopenharmony_ci endPoints: al.endpoints, 131fb726d48Sopenharmony_ci }; 132fb726d48Sopenharmony_ci } 133fb726d48Sopenharmony_ci } 134fb726d48Sopenharmony_ci } 135fb726d48Sopenharmony_ci } 136fb726d48Sopenharmony_ci return null; 137fb726d48Sopenharmony_ci } 138fb726d48Sopenharmony_ci 139fb726d48Sopenharmony_ci private static filterEndpointNumber( 140fb726d48Sopenharmony_ci // @ts-ignore 141fb726d48Sopenharmony_ci usbEndpoints: USBEndpoint[], 142fb726d48Sopenharmony_ci dir: 'in' | 'out', 143fb726d48Sopenharmony_ci type = 'bulk' 144fb726d48Sopenharmony_ci ): number { 145fb726d48Sopenharmony_ci let endpoint = usbEndpoints.filter((element) => { 146fb726d48Sopenharmony_ci return element.direction === dir && element.type === type; 147fb726d48Sopenharmony_ci }); 148fb726d48Sopenharmony_ci return endpoint[0].endpointNumber; 149fb726d48Sopenharmony_ci } 150fb726d48Sopenharmony_ci} 151