├── .DS_Store ├── .gitignore ├── LICENSE ├── MEASURE.md ├── README.md ├── app ├── .DS_Store ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── .DS_Store │ └── main │ ├── .DS_Store │ ├── AndroidManifest.xml │ ├── java │ ├── .DS_Store │ └── com │ │ ├── .DS_Store │ │ └── hd │ │ ├── .DS_Store │ │ ├── AIOApp.kt │ │ ├── JavaWrite.java │ │ ├── KotlinWrite.kt │ │ └── MainActivity.kt │ ├── libs │ └── .DS_Store │ └── res │ ├── .DS_Store │ ├── layout │ └── activity_main.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ └── icon.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── art └── icon.png ├── build.gradle ├── gradle.properties ├── gradle ├── .DS_Store └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── javalib ├── .DS_Store ├── .gitignore ├── build.gradle ├── javalib.iml └── src │ └── main │ └── java │ └── com │ └── hd │ └── test │ └── javalib │ └── myClass.java ├── sample ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── sample.iml └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── hd │ │ └── usbserialport │ │ └── sample │ │ ├── AIOComponentHandler.kt │ │ ├── AIODeviceType.kt │ │ ├── TestSerialPortParser.kt │ │ └── TestUsbDriver.java │ └── res │ └── values │ └── strings.xml ├── settings.gradle ├── usb-serial-port-measure ├── .DS_Store ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── src │ ├── .DS_Store │ └── main │ │ ├── .DS_Store │ │ ├── AndroidManifest.xml │ │ ├── java │ │ ├── .DS_Store │ │ └── com │ │ │ ├── .DS_Store │ │ │ └── aio │ │ │ └── usbserialport │ │ │ ├── cache │ │ │ └── UsbSerialPortCache.kt │ │ │ ├── config │ │ │ └── AIOComponent.kt │ │ │ ├── device │ │ │ ├── .DS_Store │ │ │ ├── Device.kt │ │ │ ├── OthersDevice.kt │ │ │ ├── SerialPortDevice.kt │ │ │ └── UsbPortDevice.kt │ │ │ ├── listener │ │ │ ├── LogcatListener.kt │ │ │ └── ReceiveResultListener.kt │ │ │ ├── method │ │ │ └── AIODeviceMeasure.kt │ │ │ ├── parser │ │ │ ├── DataPackageEntity.kt │ │ │ ├── EmptyParser.kt │ │ │ └── Parser.kt │ │ │ ├── result │ │ │ ├── ParserResult.kt │ │ │ └── PlaceholderResult.kt │ │ │ └── utils │ │ │ ├── DeviceIdUtil.kt │ │ │ ├── ParcelableUtil.kt │ │ │ └── PreferenceUtil.kt │ │ └── res │ │ ├── values-zh-rCN │ │ └── strings.xml │ │ └── values │ │ └── strings.xml └── usb-serial-port-measure.iml ├── usb-with-serial-port.iml └── usbserialport ├── .DS_Store ├── .gitignore ├── CMakeLists.txt ├── build.gradle ├── proguard-rules.pro ├── src ├── .DS_Store └── main │ ├── .DS_Store │ ├── AndroidManifest.xml │ ├── cpp │ ├── SerialPort.c │ ├── SerialPort.h │ ├── gen_SerialPort_h.sh │ └── run_emulator.sh │ ├── java │ ├── android │ │ └── serialport │ │ │ ├── SerialPort.java │ │ │ └── SerialPortFinder.java │ └── com │ │ └── hd │ │ └── serialport │ │ ├── config │ │ ├── MeasureStatus.kt │ │ └── UsbPortDeviceType.kt │ │ ├── engine │ │ ├── Engine.kt │ │ ├── SerialPortEngine.kt │ │ └── UsbPortEngine.kt │ │ ├── help │ │ ├── RequestPermissionBroadCastReceiver.kt │ │ ├── RequestUsbPermission.kt │ │ ├── RootCmd.kt │ │ └── SystemSecurity.kt │ │ ├── listener │ │ ├── MeasureListener.kt │ │ ├── SerialPortMeasureListener.kt │ │ └── UsbMeasureListener.kt │ │ ├── method │ │ └── DeviceMeasureController.kt │ │ ├── param │ │ ├── MeasureParameter.kt │ │ ├── SerialPortMeasureParameter.kt │ │ └── UsbMeasureParameter.kt │ │ ├── reader │ │ ├── .DS_Store │ │ ├── ReadWriteRunnable.kt │ │ ├── SerialPortReadWriteRunnable.kt │ │ └── UsbReadWriteRunnable.kt │ │ ├── usb_driver │ │ ├── CdcAcmSerialDriver.java │ │ ├── Ch34xSerialDriver.java │ │ ├── CommonUsbSerialDriver.java │ │ ├── CommonUsbSerialPort.java │ │ ├── Cp21xxSerialDriver.java │ │ ├── FtdiSerialDriver.java │ │ ├── ProbeTable.java │ │ ├── ProlificSerialDriver.java │ │ ├── UsbId.java │ │ ├── UsbSerialDriver.java │ │ ├── UsbSerialPort.java │ │ ├── UsbSerialProber.java │ │ └── extend │ │ │ └── UsbExtendDriver.java │ │ └── utils │ │ ├── HexDump.java │ │ └── L.kt │ ├── jniLibs │ ├── arm64-v8a │ │ └── libserial_port.so │ ├── armeabi-v7a │ │ └── libserial_port.so │ ├── armeabi │ │ └── libserial_port.so │ ├── mips │ │ └── libserial_port.so │ ├── mips64 │ │ └── libserial_port.so │ ├── x86 │ │ └── libserial_port.so │ └── x86_64 │ │ └── libserial_port.so │ └── res │ ├── values-zh-rCN │ └── strings.xml │ └── values │ └── strings.xml └── usbserialport.iml /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.DS_Store 3 | *.iml 4 | .gradle 5 | /local.properties 6 | /.idea/workspace.xml 7 | /.idea/libraries 8 | .DS_Store 9 | /build 10 | /captures 11 | .idea/ 12 | .externalNativeBuild 13 | -------------------------------------------------------------------------------- /MEASURE.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 |

usb-serial-port-measure

5 |

6 | 7 |

8 | 9 | **usb-serial-port-measure是对usbserialport的深度封装,力求用最少代码完成usb及串口设备的测量** 10 | 11 | **android studio 引入:** 12 | 13 | ``` 14 | dependencies { 15 | implementation 'com.hd:usb-serial-port-measure:last-version@aar' 16 | implementation 'com.hd:usbserialport:last-version' 17 | } 18 | ``` 19 | 20 | **用法:** 21 | 22 | **1.在application 初始化:** 23 | 24 | ``` 25 | public class AIOApp extends Application { 26 | @Override 27 | public void onCreate() { 28 | super.onCreate(); 29 | AIODeviceMeasure.INSTANCE.init(this, BuildConfig.DEBUG, new AIOComponent() { 30 | @Override 31 | public MeasureParameter getMeasureParameter(Context context, int type) { 32 | //根据类型返回测量参数 SerialPortMeasureParameter or UsbMeasureParameter 33 | return null; 34 | } 35 | 36 | @Override 37 | public Parser getParser(int type) { 38 | //根据类型返回测量数据解析类 39 | return null; 40 | } 41 | 42 | @Override 43 | public UsbSerialPort getUsbSerialPort(Context context, int type) { 44 | //根据类型返回UsbSerialPort ,针对usb 设备 45 | return null; 46 | } 47 | 48 | @Override 49 | public String getSerialPortPath(Context context, int type) { 50 | //根据类型返回串口设备地址 ,针对串口设备 51 | return null; 52 | } 53 | 54 | @Override 55 | public List getInitializationInstructInstruct(int type) { 56 | //根据类型返回针对设备初始化指令 57 | return null; 58 | } 59 | 60 | @Override 61 | public List getReleaseInstruct(int type) { 62 | //根据类型返回针对设备结束指令 63 | return null; 64 | } 65 | }); 66 | } 67 | } 68 | 69 | ``` 70 | 71 | **2.开始测量** 72 | ``` 73 | @Override 74 | protected void onResume() { 75 | super.onResume(); 76 | L.INSTANCE.d("onResume"); 77 | AIODeviceMeasure.INSTANCE.with(/*设备标示id,根据该标示查找解析类*/, new ReceiveResultListener() { 78 | @Override 79 | public void receive(@NonNull ParserResult parserResult) { 80 | L.INSTANCE.d("receive : "+parserResult.toString()); 81 | } 82 | 83 | @Override 84 | public void error(@NonNull String msg) { 85 | L.INSTANCE.d("error : "+msg); 86 | } 87 | }).startMeasure(); 88 | } 89 | 90 | ``` 91 | 92 | **3.解析类必须继承Parser类** 93 | ``` 94 | public class TestParser extends Parser { 95 | 96 | @Override 97 | public void asyncWrite() { 98 | super.asyncWrite(); 99 | //处于while循环中 100 | getWriteComplete().set(true);//跳出循环 101 | } 102 | 103 | @Override 104 | public void parser(@NotNull byte[] data) { 105 | //实现解析 106 | complete();//完成测量 107 | error();//测量错误 108 | } 109 | } 110 | 111 | ``` 112 | 113 | **4.停止测量(测量错误及完成测量后默认停止)** 114 | ``` 115 | @Override 116 | protected void onPause() { 117 | super.onPause(); 118 | L.INSTANCE.d("onPause"); 119 | AIODeviceMeasure.INSTANCE.stopMeasure(); 120 | } 121 | 122 | ``` 123 | 124 | **License** 125 | 126 | Licensed under the Apache License, Version 2.0 (the "License"); 127 | you may not use this file except in compliance with the License. 128 | You may obtain a copy of the License at 129 | 130 | http://www.apache.org/licenses/LICENSE-2.0 131 | 132 | Unless required by applicable law or agreed to in writing, software 133 | distributed under the License is distributed on an "AS IS" BASIS, 134 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135 | See the License for the specific language governing permissions and 136 | limitations under the License. 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 |

usbserialport

5 |

6 | 7 |

8 | 9 | **2021年5月更新: 因为很久没有参与硬件串口方面的工作,在加上手头并没有实际的硬件设备,所以对于大家提出的现实问题我能给与的帮助比较有限,因此本项目不在维护。** 10 | 11 | **本库使用kotlin语言开发,提供android系统下usb转串口及串口(UART,RS232)通信方式** 12 | 13 | **依赖本库的工程需要提供kotlin支持,若无法提供可参考本库底层实现 [参考串口通信源码](https://github.com/cepr/android-serialport-api) [参考usb转串口源码](https://github.com/mik3y/usb-serial-for-android)** 14 | 15 | **[基于本库开发的简单调试工具](https://github.com/HelloHuDi/usbSerialPortTools)** 16 | 17 | **[调试工具apk下载](https://raw.githubusercontent.com/HelloHuDi/usbSerialPortTools/master/app/release/app-release.apk)** 18 | 19 | **android studio 添加** 20 | 21 | ``` 22 | dependencies { 23 | implementation 'com.hd:usbserialport:last-version' 24 | } 25 | ``` 26 | **注意:usbserialport只实现底层读写功能,实际使用建议再封装一层,这里提供一个简单的封装库 [usb-serial-port-measure](MEASURE.md)** 27 | 28 | **用法:** 29 | 30 | **1.在application 初始化:** 31 | ``` 32 | public class AIOApp extends Application { 33 | @Override 34 | public void onCreate() { 35 | super.onCreate(); 36 | DeviceMeasureController.INSTANCE.init(this,BuildConfig.DEBUG); 37 | } 38 | } 39 | ``` 40 | 41 | **2.扫描设备** 42 | ``` 43 | DeviceMeasureController.INSTANCE.scanSerialPort();//扫描串口 44 | 45 | DeviceMeasureController.INSTANCE.scanUsbPort();//扫描usb转串口 46 | ``` 47 | 48 | **3.开始测量** 49 | 50 | **3.1 usb转串口测量** 51 | ``` 52 | //测量所有设备 53 | @Override 54 | protected void onResume() { 55 | super.onResume(); 56 | DeviceMeasureController.INSTANCE.measure(DeviceMeasureController.INSTANCE.scanUsbPort(),new UsbMeasureParameter(), new UsbMeasureListener() { 57 | @Override 58 | public void measuring(@Nullable Object tag,UsbSerialPort usbSerialPort, byte[] data) { 59 | //处理返回数据 60 | } 61 | 62 | @Override 63 | public void write(@Nullable Object tag,UsbSerialPort usbSerialPort) { 64 | //允许持续性写入数据 65 | try { 66 | usbSerialPort.write(new byte[]{(byte) 0xff, (byte) 0xff},1000); 67 | } catch (IOException e) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | 72 | @Override 73 | public void measureError(@Nullable Object tag,String message) { 74 | 75 | } 76 | }); 77 | } 78 | ``` 79 | ``` 80 | //测量单个目标设备 81 | @Override 82 | protected void onResume() { 83 | super.onResume(); 84 | //根据实际选择情况 85 | UsbSerialPort port=DeviceMeasureController.INSTANCE.scanUsbPort().get(0).getPorts().get(0); 86 | DeviceMeasureController.INSTANCE.measure(port, new UsbMeasureParameter(115200,8,1,0), new UsbMeasureListener() { 87 | @Override 88 | public void measuring(@Nullable Object tag,UsbSerialPort usbSerialPort, byte[] data) { 89 | //处理返回数据 90 | } 91 | 92 | @Override 93 | public void write(@Nullable Object tag,UsbSerialPort usbSerialPort) { 94 | //允许持续性写入数据 95 | try { 96 | usbSerialPort.write(new byte[]{(byte) 0xff, (byte) 0xff},1000); 97 | } catch (IOException e) { 98 | e.printStackTrace(); 99 | } 100 | } 101 | 102 | @Override 103 | public void measureError(@Nullable Object tag,String message) { 104 | 105 | } 106 | }); 107 | } 108 | 109 | ``` 110 | 111 | **3.2 串口测量** 112 | ``` 113 | //测量所有设备 114 | @Override 115 | protected void onResume() { 116 | super.onResume(); 117 | DeviceMeasureController.INSTANCE.measure(null, new SerialPortMeasureParameter(), new SerialPortMeasureListener() { 118 | @Override 119 | public void measuring(@Nullable Object tag,String path, byte[] data) { 120 | //处理返回数据 121 | } 122 | 123 | @Override 124 | public void write(@Nullable Object tag,OutputStream outputStream) { 125 | //允许持续性写入数据 126 | try { 127 | outputStream.write(new byte[]{(byte) 0xff, (byte) 0xff}); 128 | } catch (IOException e) { 129 | e.printStackTrace(); 130 | } 131 | } 132 | 133 | @Override 134 | public void measureError(@Nullable Object tag,String message) { 135 | 136 | } 137 | }); 138 | } 139 | ``` 140 | ``` 141 | //测量单个目标设备 142 | @Override 143 | protected void onResume() { 144 | super.onResume(); 145 | String targetDevicePath="/dev/ttyS3"; 146 | DeviceMeasureController.INSTANCE.measure(new SerialPortMeasureParameter(targetDevicePath,115200,0), new SerialPortMeasureListener() { 147 | @Override 148 | public void measuring(@Nullable Object tag,String path, byte[] data) { 149 | //处理返回数据 150 | } 151 | 152 | @Override 153 | public void write(@Nullable Object tag,OutputStream outputStream) { 154 | //允许持续性写入数据 155 | try { 156 | outputStream.write(new byte[]{(byte) 0xff, (byte) 0xff}); 157 | } catch (IOException e) { 158 | e.printStackTrace(); 159 | } 160 | } 161 | 162 | @Override 163 | public void measureError(@Nullable Object tag,String message) { 164 | 165 | } 166 | }); 167 | } 168 | 169 | 170 | ``` 171 | 172 | **3.测量阶段发送指令** 173 | ``` 174 | DeviceMeasureController.INSTANCE.write() 175 | ``` 176 | 177 | **4.停止测量** 178 | ``` 179 | DeviceMeasureController.INSTANCE.stop() 180 | ``` 181 | 182 | **5.usb驱动程序扩展** 183 | ``` 184 | //最新版本提供usb 驱动程序扩展功能,允许外部扩展或替换库自带驱动程序,实现自定义操作 185 | //本着开源精神,若有其他驱动或者发现本库驱动存在的问题,请向我提commit,方便后面的朋友使用 186 | List>> list = Arrays.asList( 187 | new Pair>("custom", TestUsbDriver.class)) 188 | new UsbExtendDriver.Extender().setDrivers().extend() 189 | ``` 190 | 191 | **License** 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | 205 | -------------------------------------------------------------------------------- /app/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/.DS_Store -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | android { 5 | compileSdkVersion rootProject.android_compileSdkVersion 6 | defaultConfig { 7 | minSdkVersion rootProject.android_minSdkVersion 8 | targetSdkVersion rootProject.android_targetSdkVersion 9 | applicationId "com.hd" 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | //noinspection GradleCompatible 28 | implementation lib_appcompat 29 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 30 | testImplementation 'junit:junit:4.12' 31 | api project(':sample') 32 | } 33 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/hd/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/.DS_Store -------------------------------------------------------------------------------- /app/src/main/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/.DS_Store -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/java/.DS_Store -------------------------------------------------------------------------------- /app/src/main/java/com/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/java/com/.DS_Store -------------------------------------------------------------------------------- /app/src/main/java/com/hd/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/java/com/hd/.DS_Store -------------------------------------------------------------------------------- /app/src/main/java/com/hd/AIOApp.kt: -------------------------------------------------------------------------------- 1 | package com.hd 2 | 3 | import android.app.Application 4 | import com.aio.usbserialport.method.AIODeviceMeasure 5 | import com.hd.usbserialport.sample.AIOComponentHandler 6 | 7 | 8 | /** 9 | * Created by hd on 2017/8/29 . 10 | * 11 | */ 12 | class AIOApp : Application() { 13 | override fun onCreate() { 14 | super.onCreate() 15 | AIODeviceMeasure.init(this, BuildConfig.DEBUG, AIOComponentHandler()) 16 | 17 | //扩展usb 驱动 18 | //当pair.first填写成 DriversType下的已知类型(USB_CP21xx,USB_PL2303...),理论上扩展的driver将会替换库默认的driver 19 | //所以新增driver的type,最好不要使用DriversType类型 20 | // val list = listOf>>(Pair("custom", TestUsbDriver::class.java)) 21 | // UsbExtendDriver.Extender().setDrivers(list as MutableList>>).extend() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/hd/JavaWrite.java: -------------------------------------------------------------------------------- 1 | package com.hd; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.util.Pair; 5 | 6 | import com.hd.serialport.listener.SerialPortMeasureListener; 7 | import com.hd.serialport.method.DeviceMeasureController; 8 | import com.hd.serialport.param.SerialPortMeasureParameter; 9 | import com.hd.serialport.usb_driver.UsbSerialDriver; 10 | import com.hd.serialport.usb_driver.extend.UsbExtendDriver; 11 | import com.hd.usbserialport.sample.TestUsbDriver; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | import java.io.OutputStream; 17 | import java.util.ArrayList; 18 | import java.util.Arrays; 19 | import java.util.List; 20 | 21 | /** 22 | * Created by hd on 2019-07-08 . 23 | */ 24 | public class JavaWrite extends AppCompatActivity { 25 | 26 | public void testA(){ 27 | DeviceMeasureController.INSTANCE.measure(new SerialPortMeasureParameter(), new SerialPortMeasureListener(){ 28 | @Override 29 | public void measureError(@Nullable Object tag, @NotNull String message) { 30 | 31 | } 32 | 33 | @Override 34 | public void write(@Nullable Object tag, @NotNull OutputStream outputStream) { 35 | 36 | } 37 | 38 | @Override 39 | public void measuring(@Nullable Object tag, @NotNull String path, @NotNull byte[] data) { 40 | 41 | } 42 | }); 43 | 44 | DeviceMeasureController.INSTANCE.write(new ArrayList(), null); 45 | } 46 | 47 | public void testB(){ 48 | List>> list = Arrays.asList( 49 | new Pair>("custom", TestUsbDriver.class)); 50 | new UsbExtendDriver.Extender().setDrivers(list).extend(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/hd/KotlinWrite.kt: -------------------------------------------------------------------------------- 1 | package com.hd 2 | 3 | import android.support.v7.app.AppCompatActivity 4 | import com.hd.serialport.listener.SerialPortMeasureListener 5 | import com.hd.serialport.method.DeviceMeasureController 6 | import com.hd.serialport.param.SerialPortMeasureParameter 7 | import java.io.OutputStream 8 | 9 | 10 | /** 11 | * Created by hd on 2019-07-08 . 12 | * 13 | */ 14 | 15 | class KotlinWrite : AppCompatActivity() { 16 | 17 | fun testA(){ 18 | val customTag= "自定义tag" 19 | DeviceMeasureController.measure(SerialPortMeasureParameter(tag = customTag),object : SerialPortMeasureListener{ 20 | 21 | override fun measuring(tag: Any?, path: String, data: ByteArray) { 22 | //根据tag响应 23 | } 24 | 25 | override fun write(tag: Any?, outputStream: OutputStream) { 26 | //根据tag响应 27 | } 28 | 29 | override fun measureError(tag: Any?, message: String) { 30 | //根据tag响应 31 | } 32 | }) 33 | 34 | //停止指定的串口,不传或者传null停止所有已经打开的串口 35 | DeviceMeasureController.write(listOf(),customTag) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/hd/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.hd 2 | 3 | import android.os.Bundle 4 | import android.support.v7.app.AppCompatActivity 5 | import com.aio.usbserialport.listener.ReceiveResultListener 6 | import com.aio.usbserialport.method.AIODeviceMeasure 7 | import com.aio.usbserialport.result.ParserResult 8 | import com.hd.serialport.utils.L 9 | import com.hd.usbserialport.sample.AIODeviceType 10 | 11 | 12 | /** 13 | * Created by hd on 2017/8/29 . 14 | * 15 | */ 16 | class MainActivity : AppCompatActivity() { 17 | 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | setContentView(R.layout.activity_main) 21 | } 22 | 23 | override fun onResume() { 24 | super.onResume() 25 | AIODeviceMeasure.with(AIODeviceType.DEBUG_DEVICE, object : ReceiveResultListener { 26 | override fun receive(parserResult: ParserResult) { 27 | L.d("receive : $parserResult") 28 | } 29 | 30 | override fun error(msg: String) { 31 | L.d("error : $msg") 32 | } 33 | }).startMeasure() 34 | } 35 | 36 | override fun onPause() { 37 | super.onPause() 38 | AIODeviceMeasure.stopMeasure() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/libs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/libs/.DS_Store -------------------------------------------------------------------------------- /app/src/main/res/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/.DS_Store -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 21 | 22 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-mdpi/icon.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | usb-with-serial-port 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /art/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/art/icon.png -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.3.31' 5 | repositories { 6 | jcenter() 7 | google() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.4.1' 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 13 | classpath 'me.tatarka:gradle-retrolambda:3.7.0' 14 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' 15 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3' 16 | // NOTE: Do not place your application dependencies here; they belong 17 | // in the individual module build.gradle files 18 | } 19 | } 20 | 21 | allprojects { 22 | repositories { 23 | jcenter() 24 | google() 25 | } 26 | } 27 | 28 | task clean(type: Delete) { 29 | delete rootProject.buildDir 30 | } 31 | 32 | ext { 33 | android_compileSdkVersion = 27 34 | android_buildToolsVersion = '28.0.3' 35 | android_minSdkVersion = 17 36 | android_targetSdkVersion = 27 37 | lib_appcompat = 'com.android.support:appcompat-v7:27.1.1' 38 | lib_annotations = 'com.android.support:support-annotations:27.1.1' 39 | } 40 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /gradle/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/gradle/.DS_Store -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Mar 29 09:27:02 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /javalib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/javalib/.DS_Store -------------------------------------------------------------------------------- /javalib/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml -------------------------------------------------------------------------------- /javalib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java-library' 2 | 3 | dependencies { 4 | implementation fileTree(dir: 'libs', include: ['*.jar']) 5 | } 6 | 7 | sourceCompatibility = "1.7" 8 | targetCompatibility = "1.7" 9 | -------------------------------------------------------------------------------- /javalib/javalib.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /javalib/src/main/java/com/hd/test/javalib/myClass.java: -------------------------------------------------------------------------------- 1 | package com.hd.test.javalib; 2 | 3 | public class myClass { 4 | 5 | public static void main(String args[]) { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | android { 4 | compileSdkVersion rootProject.android_compileSdkVersion 5 | buildToolsVersion rootProject.android_buildToolsVersion 6 | defaultConfig { 7 | minSdkVersion rootProject.android_minSdkVersion 8 | targetSdkVersion rootProject.android_targetSdkVersion 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | testImplementation 'junit:junit:4.12' 24 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 25 | implementation lib_annotations 26 | // api project(':usb-serial-port-measure') 27 | // api project(':usbserialport') 28 | api 'com.hd:usb-serial-port-measure:0.3.4@aar' 29 | api 'com.hd:usbserialport:0.4.1' 30 | } 31 | -------------------------------------------------------------------------------- /sample/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/hd/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /sample/src/main/java/com/hd/usbserialport/sample/AIOComponentHandler.kt: -------------------------------------------------------------------------------- 1 | package com.hd.usbserialport.sample 2 | 3 | import android.content.Context 4 | import com.aio.usbserialport.cache.UsbSerialPortCache 5 | import com.aio.usbserialport.config.AIOComponent 6 | import com.aio.usbserialport.device.Device 7 | import com.aio.usbserialport.parser.Parser 8 | import com.hd.serialport.param.MeasureParameter 9 | import com.hd.serialport.param.SerialPortMeasureParameter 10 | import com.hd.serialport.usb_driver.UsbSerialPort 11 | 12 | 13 | /** 14 | * Created by hd on 2017/9/2 . 15 | * 16 | */ 17 | class AIOComponentHandler : AIOComponent { 18 | 19 | override fun getOthersDevice(context: Context, type: Int, parser: Parser): Device? { 20 | return null 21 | } 22 | 23 | /** 24 | * provide measure parameter[SerialPortMeasureParameter] or [com.hd.serialport.param.UsbMeasureParameter] 25 | */ 26 | override fun getMeasureParameter(context: Context, type: Int): MeasureParameter? { 27 | if (type == AIODeviceType.UNKNOWN_DEVICE) throw NullPointerException("unknown aio type") 28 | var parameter: MeasureParameter? = null 29 | val path = getSerialPortPath(context, type) 30 | when (type) { 31 | AIODeviceType.DEBUG_DEVICE -> parameter = SerialPortMeasureParameter(path) 32 | } 33 | return parameter 34 | } 35 | 36 | /** 37 | * provide measure parser[Parser] 38 | */ 39 | override fun getParser(type: Int): Parser? { 40 | var parse: Parser? = null 41 | when (type) { 42 | AIODeviceType.UNKNOWN_DEVICE -> throw NullPointerException("unknown aio type") 43 | AIODeviceType.DEBUG_DEVICE -> parse = TestSerialPortParser() 44 | } 45 | return parse 46 | } 47 | 48 | /** 49 | * provide usb port[UsbSerialPort]for measure 50 | */ 51 | override fun getUsbSerialPort(context: Context, type: Int): UsbSerialPort? { 52 | if (type == AIODeviceType.UNKNOWN_DEVICE) throw NullPointerException("unknown aio type") 53 | return UsbSerialPortCache.newInstance(context, type).getUsbPortCache() 54 | } 55 | 56 | /** 57 | * provide serial port path for measure 58 | */ 59 | override fun getSerialPortPath(context: Context, type: Int): String? { 60 | return when (type) { 61 | AIODeviceType.UNKNOWN_DEVICE -> throw NullPointerException("unknown aio type") 62 | AIODeviceType.DEBUG_DEVICE -> "/dev/ttyS3" 63 | else -> UsbSerialPortCache.newInstance(context, type).getSerialPortCache() 64 | } 65 | } 66 | 67 | /** 68 | * provide initialization instruct at start measure stage 69 | */ 70 | override fun getInitializationInstructInstruct(type: Int): List? { 71 | var instructList: List? = null 72 | when (type) { 73 | AIODeviceType.UNKNOWN_DEVICE -> throw NullPointerException("unknown aio type") 74 | AIODeviceType.DEBUG_DEVICE -> instructList = listOf(byteArrayOf(2.toByte(), 15.toByte(), 6.toByte()), byteArrayOf(7.toByte(), 34.toByte(), 23.toByte())) 75 | } 76 | return instructList 77 | } 78 | 79 | /** 80 | * provide release instruct at end measure stage 81 | */ 82 | override fun getReleaseInstruct(type: Int): List? { 83 | var instructList: List? = null 84 | when (type) { 85 | AIODeviceType.UNKNOWN_DEVICE -> throw NullPointerException("unknown aio type") 86 | } 87 | return instructList 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/hd/usbserialport/sample/AIODeviceType.kt: -------------------------------------------------------------------------------- 1 | package com.hd.usbserialport.sample 2 | 3 | 4 | /** 5 | * Created by hd on 2017/8/28 . 6 | * aio device type 7 | */ 8 | object AIODeviceType{ 9 | 10 | /** 11 | * 未知设备 12 | */ 13 | val UNKNOWN_DEVICE = -1 14 | /** 15 | * 调试 16 | */ 17 | val DEBUG_DEVICE = 0 18 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/hd/usbserialport/sample/TestSerialPortParser.kt: -------------------------------------------------------------------------------- 1 | package com.hd.usbserialport.sample 2 | 3 | import com.hd.serialport.utils.L 4 | import com.aio.usbserialport.cache.UsbSerialPortCache 5 | import com.aio.usbserialport.parser.Parser 6 | import com.aio.usbserialport.result.PlaceholderResult 7 | import java.util.* 8 | 9 | 10 | /** 11 | * Created by hd on 2017/8/29 . 12 | * 13 | */ 14 | class TestSerialPortParser : Parser() { 15 | 16 | private var count = 100 17 | 18 | override fun asyncWrite() { 19 | super.asyncWrite() 20 | if (count > 0) { 21 | writeInitializationInstructAgain(10) 22 | count-- 23 | } 24 | UsbSerialPortCache.newInstance(device!!.context).getSerialPortCache() 25 | } 26 | 27 | override fun parser(data: ByteArray) { 28 | L.d("接收数据:" + Arrays.toString(data) + "=" + count) 29 | if (count <= 0) { 30 | complete(PlaceholderResult("成功"), true) 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/hd/usbserialport/sample/TestUsbDriver.java: -------------------------------------------------------------------------------- 1 | package com.hd.usbserialport.sample; 2 | 3 | import android.hardware.usb.UsbDevice; 4 | import android.hardware.usb.UsbDeviceConnection; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.hd.serialport.usb_driver.CommonUsbSerialDriver; 8 | import com.hd.serialport.usb_driver.CommonUsbSerialPort; 9 | import com.hd.serialport.usb_driver.UsbSerialDriver; 10 | import com.hd.serialport.usb_driver.UsbSerialPort; 11 | 12 | import java.io.IOException; 13 | import java.util.LinkedHashMap; 14 | import java.util.Map; 15 | 16 | 17 | /** 18 | * Created by hd on 2019-08-26 . 19 | */ 20 | public class TestUsbDriver extends CommonUsbSerialDriver { 21 | 22 | public TestUsbDriver(UsbDevice mDevice) { 23 | super(mDevice); 24 | } 25 | 26 | @Override 27 | public UsbSerialPort setPort(UsbDevice mDevice) { 28 | return new TestUsbPort(mDevice, 0); 29 | } 30 | 31 | @NonNull 32 | @Override 33 | public String setDriverName() { 34 | return "test"; 35 | } 36 | 37 | public class TestUsbPort extends CommonUsbSerialPort{ 38 | 39 | public TestUsbPort(UsbDevice device, int portNumber) { 40 | super(device, portNumber); 41 | } 42 | 43 | @Override 44 | public UsbSerialDriver getDriver() { 45 | return null; 46 | } 47 | 48 | @Override 49 | public void open(UsbDeviceConnection connection) throws IOException { 50 | 51 | } 52 | 53 | @Override 54 | public void close() throws IOException { 55 | 56 | } 57 | 58 | @Override 59 | public int read(byte[] dest, int timeoutMillis) throws IOException { 60 | return 0; 61 | } 62 | 63 | @Override 64 | public int write(byte[] src, int timeoutMillis) throws IOException { 65 | return 0; 66 | } 67 | 68 | @Override 69 | public void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException { 70 | 71 | } 72 | 73 | @Override 74 | public boolean getCD() throws IOException { 75 | return false; 76 | } 77 | 78 | @Override 79 | public boolean getCTS() throws IOException { 80 | return false; 81 | } 82 | 83 | @Override 84 | public boolean getDSR() throws IOException { 85 | return false; 86 | } 87 | 88 | @Override 89 | public boolean getDTR() throws IOException { 90 | return false; 91 | } 92 | 93 | @Override 94 | public void setDTR(boolean value) throws IOException { 95 | 96 | } 97 | 98 | @Override 99 | public boolean getRI() throws IOException { 100 | return false; 101 | } 102 | 103 | @Override 104 | public boolean getRTS() throws IOException { 105 | return false; 106 | } 107 | 108 | @Override 109 | public void setRTS(boolean value) throws IOException { 110 | 111 | } 112 | 113 | } 114 | 115 | //本方法名必须这样写,否则报错 116 | public static Map getSupportedDevices() { 117 | final Map supportedDevices = new LinkedHashMap(); 118 | //add vendor and product 119 | // supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ARDUINO), new int[]{UsbId.ARDUINO_UNO, UsbId.ARDUINO_UNO_R3, 120 | // UsbId.ARDUINO_MEGA_2560, UsbId.ARDUINO_MEGA_2560_R3, 121 | // UsbId.ARDUINO_SERIAL_ADAPTER, UsbId.ARDUINO_SERIAL_ADAPTER_R3, 122 | // UsbId.ARDUINO_MEGA_ADK, UsbId.ARDUINO_MEGA_ADK_R3, 123 | // UsbId.ARDUINO_LEONARDO, UsbId.ARDUINO_MICRO,}); 124 | return supportedDevices; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | sample 3 | 4 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':usb-serial-port-measure', ':usbserialport', ':javalib', ':sample' 2 | -------------------------------------------------------------------------------- /usb-serial-port-measure/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usb-serial-port-measure/.DS_Store -------------------------------------------------------------------------------- /usb-serial-port-measure/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml -------------------------------------------------------------------------------- /usb-serial-port-measure/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'com.github.dcendents.android-maven' 4 | apply plugin: 'com.jfrog.bintray' 5 | 6 | /*def siteUrl = 'https://github.com/HelloHuDi/usb-with-serial-port' 7 | def gitUrl = 'https://github.com/HelloHuDi/usb-with-serial-port.git' 8 | Properties properties = new Properties() 9 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 10 | version = "0.3.4" 11 | group = "com.hd"*/ 12 | 13 | android { 14 | compileSdkVersion rootProject.android_compileSdkVersion 15 | buildToolsVersion rootProject.android_buildToolsVersion 16 | defaultConfig { 17 | minSdkVersion rootProject.android_minSdkVersion 18 | targetSdkVersion rootProject.android_targetSdkVersion 19 | versionCode 34 20 | versionName "0.3.4" 21 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 22 | } 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | sourceSets { 30 | main.java.srcDirs += 'src/main/kotlin' 31 | } 32 | } 33 | 34 | dependencies { 35 | implementation fileTree(dir: 'libs', include: ['*.jar']) 36 | testImplementation 'junit:junit:4.12' 37 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 38 | implementation lib_annotations 39 | implementation project(':usbserialport') 40 | // implementation 'com.hd:usbserialport:0.3.0' 41 | }/* 42 | bintray { 43 | user = properties.getProperty("bintray.user") 44 | key = properties.getProperty("bintray.apikey") 45 | configurations = ['archives'] 46 | pkg { 47 | repo = "maven" 48 | name = "usb-serial-port-measure" 49 | websiteUrl = siteUrl 50 | vcsUrl = gitUrl 51 | licenses = ["Apache-2.0"] 52 | publish = true 53 | } 54 | } 55 | 56 | install { 57 | repositories.mavenInstaller { 58 | // This generates POM.xml with proper parameters 59 | pom { 60 | project { 61 | packaging 'aar' 62 | //Add your description here 63 | name 'usb-serial-port-measure' 64 | description 'usb-serial-port-measure library.' 65 | url siteUrl 66 | // Set your license 67 | licenses { 68 | license { 69 | name 'The Apache Software License, Version 2.0' 70 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 71 | } 72 | } 73 | developers { 74 | developer { 75 | id 'hellohudi' 76 | name 'hellohudi' 77 | email 'chinahdwoody@gmail.com' 78 | } 79 | } 80 | scm { 81 | connection gitUrl 82 | developerConnection gitUrl 83 | url siteUrl 84 | } 85 | } 86 | } 87 | } 88 | } 89 | 90 | task sourcesJar(type: Jar) { 91 | from android.sourceSets.main.java.srcDirs 92 | classifier = 'sources' 93 | } 94 | task javadoc(type: Javadoc) { 95 | failOnError false 96 | source = android.sourceSets.main.java.srcDirs 97 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 98 | } 99 | task javadocJar(type: Jar, dependsOn: javadoc) { 100 | classifier = 'javadoc' 101 | from javadoc.destinationDir 102 | } 103 | artifacts { 104 | archives javadocJar 105 | archives sourcesJar 106 | } 107 | 108 | javadoc { 109 | options{ 110 | encoding "UTF-8" 111 | charSet 'UTF-8' 112 | author true 113 | version true 114 | links "http://docs.oracle.com/javase/7/docs/api" 115 | } 116 | } 117 | */ -------------------------------------------------------------------------------- /usb-serial-port-measure/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/hd/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /usb-serial-port-measure/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usb-serial-port-measure/src/.DS_Store -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usb-serial-port-measure/src/main/.DS_Store -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usb-serial-port-measure/src/main/java/.DS_Store -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usb-serial-port-measure/src/main/java/com/.DS_Store -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/cache/UsbSerialPortCache.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.cache 2 | 3 | import android.content.Context 4 | import android.hardware.usb.UsbDevice 5 | import android.util.Base64 6 | import com.aio.usbserialport.utils.ParcelableUtil 7 | import com.aio.usbserialport.utils.PreferenceUtil 8 | import com.hd.serialport.usb_driver.* 9 | import com.hd.serialport.utils.L 10 | 11 | /** 12 | * Created by hd on 2017/8/31 . 13 | * usb port [android.hardware.usb.UsbDevice]and 14 | * serial port[android.serialport.SerialPort] path 15 | * [com.hd.serialport.param.SerialPortMeasureParameter.devicePath]cache 16 | */ 17 | class UsbSerialPortCache constructor(val context: Context, val deviceType: Int) { 18 | 19 | companion object { 20 | fun newInstance(context: Context, deviceType: Int = 0) = UsbSerialPortCache(context, deviceType) 21 | } 22 | 23 | private val usbDevice_Name = "_usbDevice" 24 | private val usbPort_Name = "_usbPort" 25 | private val serialPort_Name = "_serialPort" 26 | 27 | fun getSerialPortCache() = PreferenceUtil.get(context, deviceType.toString()+serialPort_Name, "") as String 28 | 29 | fun getUsbDeviceCache(): UsbDevice? { 30 | if (!PreferenceUtil.contains(context, deviceType.toString() + usbDevice_Name)) return null 31 | val usbDeviceStr = PreferenceUtil.get(context, deviceType.toString() + usbDevice_Name, "") as String 32 | if (usbDeviceStr.isNotEmpty()) 33 | return UsbDevice.CREATOR.createFromParcel(ParcelableUtil.read(Base64.decode(usbDeviceStr, 0))) 34 | return null 35 | } 36 | 37 | fun getUsbPortCache(): UsbSerialPort? { 38 | if (!PreferenceUtil.contains(context, deviceType.toString()+usbPort_Name)) return null 39 | val usbDevice = getUsbDeviceCache() ?: return null 40 | val usb_type = PreferenceUtil.get(context, deviceType.toString()+usbPort_Name, 0) as Int 41 | var driver: UsbSerialDriver? = null 42 | when (usb_type) { 43 | /*UsbPortDeviceType.USB_CDC_ACM */1 -> driver = CdcAcmSerialDriver(usbDevice) 44 | /*UsbPortDeviceType.USB_CP21xx*/ 2 -> driver = Cp21xxSerialDriver(usbDevice) 45 | /*UsbPortDeviceType.USB_FTD*/ 3 -> driver = FtdiSerialDriver(usbDevice) 46 | /*UsbPortDeviceType.USB_PL2303*/4 -> driver = ProlificSerialDriver(usbDevice) 47 | /*UsbPortDeviceType.USB_CH34xx*/5 -> driver = Ch34xSerialDriver(usbDevice) 48 | } 49 | if (driver != null) { 50 | val port = driver.ports[0] 51 | L.d("get cache port success:"+driver+"="+driver.deviceType) 52 | return port 53 | } 54 | L.d("get cache port UnSuccess") 55 | return null 56 | } 57 | 58 | fun removeCachePort() { 59 | PreferenceUtil.remove(context, deviceType.toString()+usbPort_Name) 60 | PreferenceUtil.remove(context, deviceType.toString()+serialPort_Name) 61 | PreferenceUtil.remove(context, deviceType.toString() + usbDevice_Name) 62 | } 63 | 64 | fun removeAllCachePort() { 65 | PreferenceUtil.clear(context) 66 | } 67 | 68 | fun setUsbSerialPortCache(usbPort: UsbSerialPort?=null,usbDevice: UsbDevice?=null,serialPortPath: String?=null){ 69 | if(usbPort!=null){ 70 | setUsbPortCache(usbPort) 71 | }else if(usbDevice!=null){ 72 | setUsbDeviceCache(usbDevice) 73 | }else if(!serialPortPath.isNullOrEmpty()){ 74 | setSerialPortCache(serialPortPath) 75 | } 76 | } 77 | 78 | fun setSerialPortCache(serialPortPath: String) { 79 | if (!PreferenceUtil.contains(context, deviceType.toString()+serialPort_Name)) 80 | PreferenceUtil.put(context, deviceType.toString()+serialPort_Name, serialPortPath) 81 | } 82 | 83 | fun setUsbDeviceCache(usbDevice: UsbDevice) { 84 | if (!PreferenceUtil.contains(context, deviceType.toString() + usbDevice_Name)) 85 | PreferenceUtil.put(context, deviceType.toString() + usbDevice_Name, Base64.encodeToString(ParcelableUtil.write(usbDevice), 0)) 86 | } 87 | 88 | fun setUsbPortCache(usbPort: UsbSerialPort) { 89 | val usbDevice = usbPort.driver.device 90 | var usb_type = 0//UsbPortDeviceType.USB_OTHERS 91 | when (usbPort) { 92 | is CdcAcmSerialDriver.CdcAcmSerialPort -> usb_type = 1//UsbPortDeviceType.USB_CDC_ACM 93 | is Cp21xxSerialDriver.Cp21xxSerialPort -> usb_type = 2//UsbPortDeviceType.USB_CP21xx 94 | is FtdiSerialDriver.FtdiSerialPort -> usb_type = 3//UsbPortDeviceType.USB_FTD 95 | is ProlificSerialDriver.ProlificSerialPort -> usb_type = 4//UsbPortDeviceType.USB_PL2303 96 | is Ch34xSerialDriver.Ch340SerialPort -> usb_type = 5//UsbPortDeviceType.USB_CH34xx 97 | } 98 | PreferenceUtil.put(context, deviceType.toString()+usbPort_Name, usb_type) 99 | setUsbDeviceCache(usbDevice) 100 | } 101 | 102 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/config/AIOComponent.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.config 2 | 3 | import android.content.Context 4 | import com.aio.usbserialport.device.Device 5 | import com.aio.usbserialport.parser.Parser 6 | import com.hd.serialport.param.MeasureParameter 7 | import com.hd.serialport.param.SerialPortMeasureParameter 8 | import com.hd.serialport.usb_driver.UsbSerialPort 9 | 10 | 11 | /** 12 | * Created by hd on 2017/9/1 . 13 | * provide aio component 14 | */ 15 | interface AIOComponent { 16 | 17 | /** 18 | * allow extension others object of 'Device' [com.aio.usbserialport.device.OthersDevice] 19 | */ 20 | fun getOthersDevice(context: Context, type:Int,parser: Parser): Device? 21 | 22 | /** 23 | * provide measure parameter[SerialPortMeasureParameter] or [com.hd.serialport.param.UsbMeasureParameter] 24 | */ 25 | fun getMeasureParameter(context: Context, type: Int): MeasureParameter? 26 | 27 | /** 28 | * provide measure parser[Parser] 29 | */ 30 | fun getParser(type: Int): Parser? 31 | 32 | /** 33 | * provide usb port[UsbSerialPort]for measure 34 | */ 35 | fun getUsbSerialPort(context: Context, type: Int): UsbSerialPort? 36 | 37 | /** 38 | * provide serial port path for measure 39 | */ 40 | fun getSerialPortPath(context: Context, type: Int): String? 41 | 42 | /** 43 | * provide initialization instruct at start measure stage 44 | */ 45 | fun getInitializationInstructInstruct(type: Int): List? 46 | 47 | /** 48 | * provide release instruct at end measure stage 49 | */ 50 | fun getReleaseInstruct(type: Int): List? 51 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/device/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usb-serial-port-measure/src/main/java/com/aio/usbserialport/device/.DS_Store -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/device/Device.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.device 2 | 3 | import android.content.Context 4 | import android.os.SystemClock 5 | import com.aio.usbserialport.R 6 | import com.aio.usbserialport.config.AIOComponent 7 | import com.aio.usbserialport.listener.LogcatListener 8 | import com.aio.usbserialport.listener.ReceiveResultListener 9 | import com.aio.usbserialport.method.AIODeviceMeasure 10 | import com.aio.usbserialport.parser.DataPackageEntity 11 | import com.aio.usbserialport.parser.Parser 12 | import com.aio.usbserialport.result.ParserResult 13 | import com.hd.serialport.config.MeasureStatus 14 | import com.hd.serialport.method.DeviceMeasureController 15 | import com.hd.serialport.usb_driver.UsbSerialPort 16 | import com.hd.serialport.utils.L 17 | import java.io.OutputStream 18 | import java.util.* 19 | import java.util.concurrent.LinkedBlockingQueue 20 | 21 | /** 22 | * Created by hd on 2017/8/28 . 23 | * 24 | */ 25 | @Suppress("LeakingThis") 26 | abstract class Device(val context: Context, val aioDeviceType: Int, val parser: Parser) { 27 | 28 | val dataQueue = LinkedBlockingQueue() 29 | 30 | val outputStreamList = LinkedList() 31 | 32 | val usbSerialPortList = LinkedList() 33 | 34 | var logcatListener: LogcatListener? = null 35 | 36 | var listener: ReceiveResultListener? = null 37 | 38 | var status = MeasureStatus.PREPARE 39 | 40 | private var single = true 41 | 42 | protected var t: List? = null 43 | 44 | protected var aioComponent: AIOComponent? = null 45 | 46 | protected abstract fun measure() 47 | 48 | protected abstract fun release() 49 | 50 | protected fun addLogcat(msg: String) { 51 | logcatListener?.logcat("logcat data :$msg") 52 | L.d(msg) 53 | } 54 | 55 | /** 56 | * provide conditions might need 57 | */ 58 | fun addCondition(t: List?) { 59 | this.t = t 60 | L.d("from the external conditions:" + t?.size + "=" + t?.toString()) 61 | } 62 | 63 | /** 64 | * set single device measure 65 | */ 66 | fun setSingle(single: Boolean) { 67 | this.single = single 68 | } 69 | 70 | /** 71 | * provide listener 72 | */ 73 | fun addListener(listener: ReceiveResultListener, logcatListener: LogcatListener?) { 74 | this.listener = listener 75 | this.logcatListener = logcatListener 76 | } 77 | 78 | /** 79 | * provide aio component 80 | */ 81 | fun addAIOComponent(aioComponent: AIOComponent?) { 82 | this.aioComponent = aioComponent 83 | } 84 | 85 | /** 86 | * write initialization device instruction 87 | */ 88 | fun initializationInstruct() = aioComponent?.getInitializationInstructInstruct(aioDeviceType) 89 | 90 | /** 91 | * write release(shut down device) instruction 92 | */ 93 | fun releaseInstruct() = aioComponent?.getReleaseInstruct(aioDeviceType) 94 | 95 | fun startMeasure() { 96 | if (!single || status == MeasureStatus.PREPARE) { 97 | status = MeasureStatus.RUNNING 98 | parser.parser(this) 99 | measure() 100 | DeviceMeasureController.write(initializationInstruct()) 101 | if (initializationInstruct() != null && initializationInstruct()!!.isNotEmpty()) 102 | initializationInstruct()!!.forEach { addLogcat("begin to write data :" + Arrays.toString(it)) } 103 | } 104 | } 105 | 106 | fun stopMeasure() { 107 | L.d("device stop:$status") 108 | if (status == MeasureStatus.RUNNING) { 109 | status = MeasureStatus.STOPPING 110 | single = true 111 | release() 112 | DeviceMeasureController.write(releaseInstruct()) 113 | SystemClock.sleep(100) 114 | DeviceMeasureController.stop() 115 | dataQueue.clear() 116 | outputStreamList.clear() 117 | usbSerialPortList.clear() 118 | t = null 119 | listener = null 120 | logcatListener = null 121 | status = MeasureStatus.STOPPED 122 | } 123 | } 124 | 125 | fun write(byteArray: ByteArray?, delay: Long = 0) { 126 | try { 127 | outputStreamList.filter { status == MeasureStatus.RUNNING }.forEach { it.write(byteArray) } 128 | usbSerialPortList.filter { status == MeasureStatus.RUNNING }.forEach { it.write(byteArray, 1000) } 129 | L.d("device write :" + Arrays.toString(byteArray)) 130 | SystemClock.sleep(delay) 131 | } catch (ignored: Exception) { 132 | L.d("device write error :" + Arrays.toString(byteArray)) 133 | } 134 | } 135 | 136 | fun write(data: List?, delay: Long = 0) { 137 | if (data != null && data.isNotEmpty()) data.filter { status == MeasureStatus.RUNNING }.forEach { write(it, delay) } 138 | } 139 | 140 | fun error(msg: String?) { 141 | listener?.error(if (msg == null || msg.isEmpty()) context.resources.getString(R.string.measure_error) else msg) 142 | AIODeviceMeasure.stopMeasure() 143 | } 144 | 145 | fun complete(parserResult: ParserResult, stop: Boolean) { 146 | listener?.receive(parserResult) 147 | if (stop) AIODeviceMeasure.stopMeasure() 148 | } 149 | 150 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/device/OthersDevice.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.device 2 | 3 | import android.content.Context 4 | import com.aio.usbserialport.parser.Parser 5 | import kotlin.concurrent.thread 6 | 7 | 8 | /** 9 | * Created by hd on 2017/9/4 . 10 | * others unknown device 11 | */ 12 | abstract class OthersDevice(context: Context, aioDeviceType:Int,parser: Parser) 13 | : Device(context,aioDeviceType, parser){ 14 | 15 | abstract fun asyncMeasure() 16 | 17 | override fun measure() { 18 | thread { asyncMeasure() } 19 | } 20 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/device/SerialPortDevice.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.device 2 | 3 | import android.content.Context 4 | import com.aio.usbserialport.parser.DataPackageEntity 5 | import com.aio.usbserialport.parser.Parser 6 | import com.hd.serialport.listener.SerialPortMeasureListener 7 | import com.hd.serialport.method.DeviceMeasureController 8 | import com.hd.serialport.param.SerialPortMeasureParameter 9 | import java.io.OutputStream 10 | import java.util.* 11 | 12 | 13 | /** 14 | * Created by hd on 2017/8/28 . 15 | * 16 | */ 17 | open class SerialPortDevice(context: Context, aioDeviceType: Int, private val parameter: SerialPortMeasureParameter, parser: Parser) 18 | : Device(context, aioDeviceType, parser), SerialPortMeasureListener { 19 | 20 | override fun write(tag: Any?, outputStream: OutputStream) { 21 | outputStreamList.add(outputStream) 22 | } 23 | 24 | override fun measure() { 25 | DeviceMeasureController.measure(parameter = parameter, listener = this) 26 | } 27 | 28 | override fun release() { 29 | } 30 | 31 | override fun measureError(tag: Any?, message: String) { 32 | error(message) 33 | } 34 | 35 | override fun measuring(tag: Any?, path: String, data: ByteArray) { 36 | dataQueue.put(DataPackageEntity(path = path, data = data)) 37 | addLogcat(path + "====" + Arrays.toString(data)) 38 | } 39 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/device/UsbPortDevice.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.device 2 | 3 | import android.content.Context 4 | import com.aio.usbserialport.parser.DataPackageEntity 5 | import com.aio.usbserialport.parser.Parser 6 | import com.hd.serialport.listener.UsbMeasureListener 7 | import com.hd.serialport.method.DeviceMeasureController 8 | import com.hd.serialport.param.UsbMeasureParameter 9 | import com.hd.serialport.usb_driver.UsbSerialPort 10 | import java.util.* 11 | 12 | /** 13 | * Created by hd on 2017/8/28 . 14 | * 15 | */ 16 | open class UsbPortDevice(context: Context, aioDeviceType:Int, private val port: UsbSerialPort? = null, private val parameter: UsbMeasureParameter, parser: Parser) 17 | : Device(context,aioDeviceType, parser), UsbMeasureListener { 18 | 19 | override fun write(tag: Any?,usbSerialPort: UsbSerialPort) { 20 | usbSerialPortList.add(usbSerialPort) 21 | } 22 | 23 | override fun measure() { 24 | DeviceMeasureController.measure(usbSerialPort = port, parameter = parameter, listener = this) 25 | } 26 | 27 | override fun release() { 28 | } 29 | 30 | override fun measureError(tag: Any?,message: String) { 31 | error(message) 32 | } 33 | 34 | override fun measuring(tag: Any?,usbSerialPort: UsbSerialPort, data: ByteArray) { 35 | dataQueue.put(DataPackageEntity(port = usbSerialPort, data = data)) 36 | addLogcat(Arrays.toString(data)) 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/listener/LogcatListener.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.listener 2 | 3 | 4 | /** 5 | * Created by hd on 2017/9/30 . 6 | * 7 | */ 8 | interface LogcatListener { 9 | 10 | fun logcat(msg: String) 11 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/listener/ReceiveResultListener.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.listener 2 | 3 | import android.support.annotation.NonNull 4 | import com.aio.usbserialport.result.ParserResult 5 | 6 | /** 7 | * Created by hd on 2017/8/31. 8 | 9 | */ 10 | interface ReceiveResultListener { 11 | 12 | /** 13 | * receive aio device response data 14 | */ 15 | fun receive(@NonNull parserResult: ParserResult) 16 | 17 | /** 18 | * measure error 19 | 20 | */ 21 | fun error(@NonNull msg: String) 22 | } 23 | -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/method/AIODeviceMeasure.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.method 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.widget.Toast 6 | import com.aio.usbserialport.R 7 | import com.aio.usbserialport.config.AIOComponent 8 | import com.aio.usbserialport.device.Device 9 | import com.aio.usbserialport.device.SerialPortDevice 10 | import com.aio.usbserialport.device.UsbPortDevice 11 | import com.aio.usbserialport.listener.LogcatListener 12 | import com.aio.usbserialport.listener.ReceiveResultListener 13 | import com.aio.usbserialport.parser.EmptyParser 14 | import com.aio.usbserialport.parser.Parser 15 | import com.hd.serialport.config.MeasureStatus 16 | import com.hd.serialport.help.RequestUsbPermission 17 | import com.hd.serialport.method.DeviceMeasureController 18 | import com.hd.serialport.param.SerialPortMeasureParameter 19 | import com.hd.serialport.param.UsbMeasureParameter 20 | import com.hd.serialport.utils.L 21 | 22 | /** 23 | * Created by hd on 2017/8/28 . 24 | * aio device measure controller 25 | */ 26 | @SuppressLint("StaticFieldLeak") 27 | object AIODeviceMeasure { 28 | 29 | private var context: Context? = null 30 | 31 | private var aioComponent: AIOComponent? = null 32 | 33 | private var status = MeasureStatus.STOPPED 34 | 35 | private var deviceMap = mutableMapOf() 36 | 37 | private var parserMap = mutableMapOf() 38 | 39 | private var single = true 40 | 41 | private var t = linkedMapOf>() 42 | 43 | /** 44 | * init measure component 45 | */ 46 | fun init(context: Context, openLog: Boolean, aioComponent: AIOComponent) { 47 | init(context,openLog,true,aioComponent) 48 | } 49 | 50 | fun init(context: Context, openLog: Boolean,requestUsbPermission: Boolean, aioComponent: AIOComponent, 51 | callback: RequestUsbPermission.RequestPermissionCallback? = null) { 52 | this.aioComponent = aioComponent 53 | AIODeviceMeasure.context = context.applicationContext 54 | DeviceMeasureController.init(AIODeviceMeasure.context!!, openLog,requestUsbPermission,callback) 55 | } 56 | 57 | /** 58 | * single detection without logcat 59 | */ 60 | fun with(aioDeviceType: Int, listener: ReceiveResultListener): AIODeviceMeasure { 61 | return with(aioDeviceType, listener, null) 62 | } 63 | 64 | /** 65 | * multiple detection without logcat 66 | */ 67 | fun with(aioDeviceTypeList: List, listenerList: List): AIODeviceMeasure { 68 | return with(aioDeviceTypeList, listenerList, null) 69 | } 70 | 71 | /** 72 | * single detection with logcat 73 | */ 74 | fun with(aioDeviceType: Int, listener: ReceiveResultListener, logcatListener: LogcatListener?): AIODeviceMeasure { 75 | single = true 76 | initDevice(aioDeviceType, listener, logcatListener) 77 | return this 78 | } 79 | 80 | /** 81 | * multiple detection with logcat 82 | */ 83 | fun with(aioDeviceTypeList: List, listenerList: List, logcatListener: LogcatListener?): AIODeviceMeasure { 84 | single = false 85 | for (index in aioDeviceTypeList.indices) { 86 | initDevice(aioDeviceTypeList[index], if (listenerList.size == aioDeviceTypeList.size) listenerList[index] else listenerList[0], logcatListener) 87 | } 88 | return this 89 | } 90 | 91 | /** 92 | * add single detection condition 93 | */ 94 | fun addCondition(t: List): AIODeviceMeasure { 95 | val par = mutableMapOf>() 96 | par[0] = t 97 | return addCondition(par) 98 | } 99 | 100 | /** 101 | * add multiple detection condition 102 | */ 103 | fun addCondition(mapT: Map>): AIODeviceMeasure { 104 | mapT.forEach { AIODeviceMeasure.t[it.key] = it.value } 105 | L.d("condition : " + mapT + "=" + mapT.size + "=" + AIODeviceMeasure.t.size) 106 | return this 107 | } 108 | 109 | /** 110 | * start measure 111 | */ 112 | fun startMeasure() { 113 | try { 114 | deviceMap.forEach { 115 | it.value.setSingle(single) 116 | if (single && t.isNotEmpty()) { 117 | it.value.addCondition(t[0]) 118 | } else if (t.containsKey(it.key)) { 119 | it.value.addCondition(t[it.key]) 120 | } 121 | it.value.startMeasure() 122 | } 123 | status = MeasureStatus.RUNNING 124 | } catch (ignored: Exception) { 125 | L.e(context!!.resources.getString(R.string.unpredictable_errors) + "=" + ignored) 126 | Toast.makeText(context!!, context!!.resources.getString(R.string.unpredictable_errors), Toast.LENGTH_SHORT).show() 127 | stopMeasure() 128 | } 129 | } 130 | 131 | /** 132 | * stop measure 133 | */ 134 | fun stopMeasure() { 135 | L.d("stop :+ $context+'='+$status") 136 | if (status == MeasureStatus.RUNNING && deviceMap.isNotEmpty()) { 137 | status = MeasureStatus.STOPPING 138 | deviceMap.forEach { it.value.stopMeasure() } 139 | deviceMap.clear() 140 | t.clear() 141 | status = MeasureStatus.STOPPED 142 | } 143 | } 144 | 145 | /** 146 | * query the device according to type 147 | */ 148 | fun getDevice(aioDeviceType: Int): Device? { 149 | return if (deviceMap.containsKey(aioDeviceType)) 150 | deviceMap[aioDeviceType] 151 | else null 152 | } 153 | 154 | /** 155 | * query the parser according to type 156 | */ 157 | fun getParser(aioDeviceType: Int): Parser? { 158 | return if (parserMap.containsKey(aioDeviceType)) 159 | parserMap[aioDeviceType] 160 | else null 161 | } 162 | 163 | private fun initDevice(aioDeviceType: Int, listener: ReceiveResultListener, logcatListener: LogcatListener?) { 164 | check(aioDeviceType) 165 | if (single) 166 | stopMeasure() 167 | val parser = aioComponent!!.getParser(aioDeviceType) ?: EmptyParser() 168 | parserMap[aioDeviceType] = parser 169 | val parameter = aioComponent!!.getMeasureParameter(context!!, aioDeviceType) 170 | val device: Device? 171 | device = when (parameter) { 172 | is SerialPortMeasureParameter -> SerialPortDevice(context!!, aioDeviceType, parameter, parser) 173 | is UsbMeasureParameter -> UsbPortDevice(context!!, aioDeviceType, aioComponent!!.getUsbSerialPort(context!!, aioDeviceType), parameter, parser) 174 | else -> aioComponent!!.getOthersDevice(context!!, aioDeviceType, parser) 175 | } 176 | if (device != null) { 177 | device.addAIOComponent(aioComponent) 178 | device.addListener(listener, logcatListener) 179 | deviceMap[aioDeviceType] = device 180 | } 181 | status = MeasureStatus.PREPARE 182 | } 183 | 184 | private fun check(aioDeviceType: Int) { 185 | if (context == null) throw RuntimeException("please initialize context in your application") 186 | if (aioDeviceType < 0) throw RuntimeException("please initialize aio device type first") 187 | if (aioComponent == null) throw NullPointerException("aio measure component config is null !!!") 188 | } 189 | 190 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/parser/DataPackageEntity.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.parser 2 | 3 | import com.hd.serialport.usb_driver.UsbSerialPort 4 | 5 | 6 | /** 7 | * Created by hd on 2017/8/28 . 8 | * @param port usb port [UsbSerialPort] 9 | * @param path serial port device path[com.hd.serialport.param.SerialPortMeasureParameter.devicePath] 10 | * @param data receive data from port[UsbSerialPort]or[android.serialport.SerialPort] 11 | */ 12 | data class DataPackageEntity (var port:UsbSerialPort?=null,var path:String?=null, var data: ByteArray) -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/parser/EmptyParser.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.parser 2 | 3 | import com.hd.serialport.utils.L 4 | import java.util.* 5 | 6 | 7 | /** 8 | * Created by hd on 2017/9/4 . 9 | * 10 | */ 11 | open class EmptyParser:Parser(){ 12 | 13 | override fun parser(data: ByteArray) { 14 | L.d("empty parser :"+ Arrays.toString(data)) 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/parser/Parser.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.parser 2 | 3 | import com.aio.usbserialport.device.Device 4 | import com.aio.usbserialport.result.ParserResult 5 | import com.hd.serialport.config.MeasureStatus 6 | import com.hd.serialport.usb_driver.UsbSerialPort 7 | import com.hd.serialport.utils.L 8 | import java.nio.BufferOverflowException 9 | import java.nio.ByteBuffer 10 | import java.util.concurrent.atomic.AtomicBoolean 11 | 12 | 13 | /** 14 | * Created by hd on 2017/8/28 . 15 | * parse the data from the usb port (or serial port) 16 | */ 17 | abstract class Parser { 18 | 19 | protected var readThread: Thread? = null 20 | 21 | protected var writeThread: Thread? = null 22 | 23 | protected val writeComplete = AtomicBoolean(false) 24 | 25 | protected var device: Device? = null 26 | 27 | protected var port: UsbSerialPort? = null 28 | 29 | protected var devicePath:String?=null 30 | 31 | protected val buffer = ByteBuffer.allocate(16 * 1024)!! 32 | 33 | fun parser(device: Device) { 34 | this.device = device 35 | if (readThread == null) readThread = Thread(Runnable { reading(device) }) 36 | readThread!!.start() 37 | if (writeThread == null) writeThread = Thread(Runnable { writing(device) }) 38 | writeThread!!.start() 39 | } 40 | 41 | private fun writing(device: Device) { 42 | while (device.status == MeasureStatus.RUNNING && !writeComplete.get()) { 43 | asyncWrite() 44 | } 45 | L.d("writing thread stop :"+device.status+"="+writeComplete.get()) 46 | } 47 | 48 | private fun reading(device: Device) { 49 | while (device.status == MeasureStatus.RUNNING) { 50 | try { 51 | val entity = device.dataQueue.take() 52 | port = entity.port 53 | devicePath = entity.path 54 | buffer.put(entity.data) 55 | parser(entity.data) 56 | }catch (ignored: BufferOverflowException){ 57 | buffer.clear() 58 | L.e("parser BufferOverflowException") 59 | }catch (e:Exception){ 60 | L.e("parser unknown Exception:$e") 61 | } 62 | } 63 | L.d("reading thread stop") 64 | } 65 | 66 | fun write(byteArray: ByteArray, delay: Long = 0) { 67 | device?.write(byteArray, delay) 68 | } 69 | 70 | fun writeInitializationInstructAgain(delay: Long = 0) { 71 | device?.write(device!!.initializationInstruct(), delay) 72 | } 73 | 74 | fun error(msg: String?=null) { 75 | device?.error(msg) 76 | clear() 77 | } 78 | 79 | fun complete(result: ParserResult, stop: Boolean) { 80 | if (stop){ 81 | clear() 82 | saveDevice() 83 | } 84 | device?.complete(result, stop) 85 | } 86 | 87 | open fun saveDevice() { 88 | L.d("save device :"+device!!.context+"="+device?.aioDeviceType+"="+port+"="+devicePath) 89 | //No caching is provided because of performance problems 90 | //UsbSerialPortCache.newInstance(device!!.context,device!!.aioDeviceType).setUsbSerialPortCache(usbPort=port,serialPortPath = devicePath) 91 | } 92 | 93 | private fun clear() { 94 | buffer.clear() 95 | if (!readThread!!.isAlive && !readThread!!.isInterrupted) 96 | readThread!!.interrupt() 97 | readThread = null 98 | if (!writeThread!!.isAlive && !writeThread!!.isInterrupted) 99 | writeThread!!.interrupt() 100 | writeThread = null 101 | } 102 | 103 | /** 104 | * allows asynchronous persistence parsing 105 | * parser complete please call [complete] 106 | * parser error please call [error] 107 | */ 108 | abstract fun parser(data: ByteArray) 109 | 110 | /** 111 | * allow asynchronous to be written{[write] or [writeInitializationInstructAgain]} all the time 112 | */ 113 | open fun asyncWrite() {} 114 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/result/ParserResult.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.result 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by hd on 2017/8/14. 7 | * 8 | */ 9 | abstract class ParserResult : Serializable 10 | -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/result/PlaceholderResult.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.result 2 | 3 | 4 | /** 5 | * Created by hd on 2017/8/29 . 6 | * 7 | */ 8 | data class PlaceholderResult(var msg:String?=null):ParserResult() -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/utils/DeviceIdUtil.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.utils 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.os.Build 6 | import android.provider.Settings 7 | import android.telephony.TelephonyManager 8 | import com.hd.serialport.utils.L 9 | import java.io.File 10 | import java.io.FileOutputStream 11 | import java.io.IOException 12 | import java.io.RandomAccessFile 13 | import java.security.MessageDigest 14 | import java.security.NoSuchAlgorithmException 15 | import java.util.* 16 | 17 | 18 | /** 19 | * Created by hd on 2017/8/31 . 20 | * the only ID identification equipment 21 | */ 22 | class DeviceIdUtil private constructor(private val context: Context) { 23 | 24 | companion object { 25 | 26 | fun newInstance(context: Context): DeviceIdUtil { 27 | return DeviceIdUtil(context) 28 | } 29 | } 30 | 31 | private val DEFAULT_NAME = "hd" 32 | 33 | /** 34 | * get pseudo unique ID 35 | */ 36 | val uniqueID: String 37 | get() { 38 | val stringBuilder = formatEmptyString(deviceID) + // 39 | formatEmptyString(androidID) + // 40 | formatEmptyString(serialNumber) + // 41 | formatEmptyString(installDeviceID) + // 42 | formatEmptyString(customID) 43 | return Md5Encrypt(stringBuilder) 44 | } 45 | 46 | private fun formatEmptyString(str: String?): String { 47 | L.d("get device's id :$str") 48 | return if (str == null || str.isEmpty()) DEFAULT_NAME else str 49 | } 50 | 51 | private fun Md5Encrypt(plainText: String): String { 52 | try { 53 | val md = MessageDigest.getInstance("MD5") 54 | md.update(plainText.toByteArray()) 55 | val b = md.digest() 56 | var i: Int 57 | val sb = StringBuilder("") 58 | for (offset in b.indices) { 59 | i = b[offset].toInt() 60 | if (i < 0) { 61 | i += 256 62 | } 63 | if (i < 16) { 64 | sb.append("0") 65 | } 66 | sb.append(Integer.toHexString(i)) 67 | } 68 | //32位加密 69 | return sb.toString()//buf.toString().substring(8, 24); //16位的加密 70 | } catch (e: NoSuchAlgorithmException) { 71 | return plainText 72 | } 73 | 74 | } 75 | 76 | /** 77 | * Android系统为开发者提供的用于标识手机设备的串号,非手机设备无法获取 78 | */ 79 | val deviceID: String 80 | @SuppressLint("HardwareIds", "MissingPermission") 81 | get() = (context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).deviceId 82 | 83 | /** 84 | * 在设备首次启动时,系统会随机生成一个64位的数字, 85 | * 并把这个数字以16进制字符串的形式保存下来,这个16进制的字符串就是ANDROID_ID,当设备被wipe后该值会被重置。 86 | * 注意:不同的设备可能会产生相同的ANDROID_ID,有些设备返回的值为null,厂商问题. 87 | * 对于CDMA设备,ANDROID_ID和TelephonyManager.getDeviceId() 返回相同的值。 88 | */ 89 | val androidID: String 90 | get() = Settings.System.getString(context.contentResolver, Settings.Secure.ANDROID_ID) 91 | 92 | /** 93 | * Android系统2.3版本以上可以通过下面的方法得到Serial Number,且非手机设备也可以通过该接口获取 94 | */ 95 | val serialNumber: String 96 | @SuppressLint("HardwareIds") 97 | get() = android.os.Build.SERIAL 98 | 99 | /** 100 | * 在程序安装后第一次运行时生成一个ID,该方式和设备唯一标识不一样, 101 | * 不同的应用程序会产生不同的ID,同一个程序重新安装也会不同。 102 | * 所以这不是设备的唯一ID,但是可以保证每个用户的ID是不同的。 103 | * 可以说是用来标识每一份应用程序的唯一ID(即Install device ID),可以用来跟踪应用的安装数量等 104 | */ 105 | val installDeviceID: String 106 | get() { 107 | var sID = "" 108 | val installation = File(context.filesDir, "INSTALLATION") 109 | try { 110 | if (!installation.exists()) { 111 | val out = FileOutputStream(installation) 112 | val id = UUID.randomUUID().toString() 113 | out.write(id.toByteArray()) 114 | out.close() 115 | } 116 | sID = readInstallationFile(installation) 117 | } catch (ignored: Exception) { 118 | } 119 | return sID 120 | } 121 | 122 | /** 123 | * 通过读取设备的ROM版本号、厂商名、CPU型号和其他硬件信息来组合出一串号码作为标识 124 | */ 125 | //2+13 位 126 | //API>=9 使用serial号 127 | val customID: String 128 | get() { 129 | var serial = "hd_serial" 130 | val m_szDevIDShort = DEFAULT_NAME + Build.BOARD.length % 10 + Build.BRAND.length % 10 + 131 | 132 | Build.CPU_ABI.length % 10 + Build.DEVICE.length % 10 + 133 | 134 | Build.DISPLAY.length % 10 + Build.HOST.length % 10 + 135 | 136 | Build.ID.length % 10 + Build.MANUFACTURER.length % 10 + 137 | 138 | Build.MODEL.length % 10 + Build.PRODUCT.length % 10 + 139 | 140 | Build.TAGS.length % 10 + Build.TYPE.length % 10 + 141 | 142 | Build.USER.length % 10 143 | try { 144 | serial = android.os.Build::class.java.getField("SERIAL").get(null).toString() 145 | } catch (ignored: Exception) { 146 | } 147 | 148 | return UUID(m_szDevIDShort.hashCode().toLong(), serial.hashCode().toLong()).toString() 149 | } 150 | 151 | @Throws(IOException::class) 152 | private fun readInstallationFile(installation: File): String { 153 | val f = RandomAccessFile(installation, "r") 154 | val bytes = ByteArray(f.length().toInt()) 155 | f.readFully(bytes) 156 | f.close() 157 | return String(bytes) 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/utils/ParcelableUtil.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.utils 2 | 3 | import android.os.Parcel 4 | import android.os.Parcelable 5 | 6 | 7 | /** 8 | * Created by hd on 2017/8/31 . 9 | * 10 | */ 11 | object ParcelableUtil{ 12 | 13 | fun write(parcelable: Parcelable): ByteArray { 14 | val parcel = Parcel.obtain() 15 | parcel.setDataPosition(0) 16 | parcelable.writeToParcel(parcel, 0) 17 | val bytes = parcel.marshall() 18 | parcel.recycle() 19 | return bytes 20 | } 21 | 22 | fun read(bytes: ByteArray): Parcel { 23 | val parcel = Parcel.obtain() 24 | parcel.unmarshall(bytes, 0, bytes.size) 25 | parcel.setDataPosition(0) 26 | return parcel 27 | } 28 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/java/com/aio/usbserialport/utils/PreferenceUtil.kt: -------------------------------------------------------------------------------- 1 | package com.aio.usbserialport.utils 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import android.util.Log 6 | import java.lang.reflect.InvocationTargetException 7 | import java.lang.reflect.Method 8 | 9 | 10 | /** 11 | * Created by hd on 2017/8/31 . 12 | * 13 | */ 14 | object PreferenceUtil{ 15 | 16 | val FILE_NAME = "usb_serial_port_measure_data" 17 | 18 | fun put(context: Context, key: String, any: Any) { 19 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 20 | val editor = sp.edit() 21 | when (any) { 22 | is String -> editor.putString(key, any) 23 | is Int -> editor.putInt(key, any) 24 | is Boolean -> editor.putBoolean(key, any) 25 | is Float -> editor.putFloat(key, any) 26 | is Long -> editor.putLong(key, any) 27 | else -> editor.putString(key, any.toString()) 28 | } 29 | SharedPreferencesCompat.apply(editor) 30 | } 31 | 32 | fun get(context: Context, key: String, defaultObject: Any): Any { 33 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 34 | if (contains(context, key)) { 35 | when (defaultObject) { 36 | is String -> return sp.getString(key, defaultObject) 37 | is Int -> return sp.getInt(key, defaultObject) 38 | is Boolean -> return sp.getBoolean(key, defaultObject) 39 | is Float -> return sp.getFloat(key, defaultObject) 40 | is Long -> return sp.getLong(key, defaultObject) 41 | else -> { 42 | Log.e("tag","==others type:$defaultObject") 43 | } 44 | } 45 | } 46 | return defaultObject 47 | } 48 | 49 | fun remove(context: Context, key: String) { 50 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 51 | val editor = sp.edit() 52 | if (contains(context, key)) { 53 | editor.remove(key) 54 | SharedPreferencesCompat.apply(editor) 55 | } 56 | } 57 | 58 | fun clear(context: Context) { 59 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 60 | val editor = sp.edit() 61 | editor.clear() 62 | SharedPreferencesCompat.apply(editor) 63 | } 64 | 65 | fun contains(context: Context, key: String): Boolean { 66 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 67 | return sp.contains(key) 68 | } 69 | 70 | fun getAll(context: Context): Map { 71 | val sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 72 | return sp.all 73 | } 74 | 75 | private object SharedPreferencesCompat { 76 | private val sApplyMethod = findApplyMethod() 77 | 78 | private fun findApplyMethod(): Method? { 79 | try { 80 | val clz = SharedPreferences.Editor::class.java 81 | return clz.getMethod("apply") 82 | } catch (e: NoSuchMethodException) { 83 | } 84 | return null 85 | } 86 | 87 | fun apply(editor: SharedPreferences.Editor) { 88 | try { 89 | if (sApplyMethod != null) { 90 | sApplyMethod.invoke(editor) 91 | return 92 | } 93 | } catch (e: IllegalArgumentException) { 94 | } catch (e: IllegalAccessException) { 95 | } catch (e: InvocationTargetException) { 96 | } 97 | editor.commit() 98 | } 99 | } 100 | 101 | } -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | sihealdevicelibrary 3 | 本次测量失败 4 | 很抱歉,出现了意料之外的错误! 5 | 6 | -------------------------------------------------------------------------------- /usb-serial-port-measure/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | sihealdevicelibrary 3 | Failure of this measurement 4 | There is an unexpected mistake! 5 | 6 | -------------------------------------------------------------------------------- /usb-with-serial-port.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /usbserialport/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/.DS_Store -------------------------------------------------------------------------------- /usbserialport/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml -------------------------------------------------------------------------------- /usbserialport/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Sets the minimum version of CMake required to build your native library. 2 | # This ensures that a certain set of CMake features is available to 3 | # your build. 4 | # android studio set CMakeLists.txt : https://developer.android.com/studio/projects/add-native-code.html 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Specifies a library name, specifies whether the library is STATIC or 9 | # SHARED, and provides relative paths to the source code. You can 10 | # define multiple libraries by adding multiple add.library() commands, 11 | # and CMake builds them for you. When you build your app, Gradle 12 | # automatically packages shared libraries with your APK. 13 | 14 | add_library( # Specifies the name of the library. 15 | serial_port 16 | 17 | # Sets the library as a shared library. 18 | SHARED 19 | 20 | # Provides a relative path to your source file(s). 21 | src/main/cpp/SerialPort.c ) 22 | 23 | find_library( # Sets the name of the path variable. 24 | log-lib 25 | 26 | # Specifies the name of the NDK library that 27 | # you want CMake to locate. 28 | log ) 29 | 30 | # Specifies libraries CMake should link to your target library. You 31 | # can link multiple libraries, such as libraries you define in this 32 | # build script, prebuilt third-party libraries, or system libraries. 33 | 34 | target_link_libraries( # Specifies the target library. 35 | serial_port 36 | 37 | # Links the target library to the log library 38 | # included in the NDK. 39 | ${log-lib} ) -------------------------------------------------------------------------------- /usbserialport/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | 4 | apply plugin: 'com.github.dcendents.android-maven' 5 | apply plugin: 'com.jfrog.bintray' 6 | def siteUrl = 'https://github.com/HelloHuDi/usb-with-serial-port' 7 | def gitUrl = 'https://github.com/HelloHuDi/usb-with-serial-port.git' 8 | Properties properties = new Properties() 9 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 10 | version = "0.4.1" 11 | group = "com.hd" 12 | 13 | android { 14 | compileSdkVersion rootProject.android_compileSdkVersion 15 | buildToolsVersion rootProject.android_buildToolsVersion 16 | defaultConfig { 17 | minSdkVersion rootProject.android_minSdkVersion 18 | targetSdkVersion rootProject.android_targetSdkVersion 19 | versionCode 12 20 | versionName "0.4.1" 21 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 22 | } 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | sourceSets { 30 | main.java.srcDirs += 'src/main/kotlin' 31 | } 32 | // externalNativeBuild { 33 | // cmake { 34 | // path 'CMakeLists.txt' 35 | // } 36 | // } 37 | } 38 | 39 | 40 | dependencies { 41 | implementation fileTree(include: '*.jar', dir: 'libs') 42 | testImplementation 'junit:junit:4.12' 43 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 44 | implementation lib_annotations 45 | } 46 | bintray { 47 | user = properties.getProperty("bintray.user") 48 | key = properties.getProperty("bintray.apikey") 49 | configurations = ['archives'] 50 | pkg { 51 | repo = "maven" 52 | name = "usb-with-serial-port" 53 | websiteUrl = siteUrl 54 | vcsUrl = gitUrl 55 | licenses = ["Apache-2.0"] 56 | publish = true 57 | } 58 | } 59 | 60 | install { 61 | repositories.mavenInstaller { 62 | // This generates POM.xml with proper parameters 63 | pom { 64 | project { 65 | packaging 'aar' 66 | //Add your description here 67 | name 'usb-with-serial-port' 68 | description 'usb-with-serial-port library.' 69 | url siteUrl 70 | // Set your license 71 | licenses { 72 | license { 73 | name 'The Apache Software License, Version 2.0' 74 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 75 | } 76 | } 77 | developers { 78 | developer { 79 | id 'hellohudi' 80 | name 'hellohudi' 81 | email 'chinahdwoody@gmail.com' 82 | } 83 | } 84 | scm { 85 | connection gitUrl 86 | developerConnection gitUrl 87 | url siteUrl 88 | } 89 | } 90 | } 91 | } 92 | } 93 | task sourcesJar(type: Jar) { 94 | from android.sourceSets.main.java.srcDirs 95 | classifier = 'sources' 96 | } 97 | task javadoc(type: Javadoc) { 98 | failOnError false 99 | source = android.sourceSets.main.java.srcDirs 100 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 101 | } 102 | task javadocJar(type: Jar, dependsOn: javadoc) { 103 | classifier = 'javadoc' 104 | from javadoc.destinationDir 105 | } 106 | artifacts { 107 | archives javadocJar 108 | archives sourcesJar 109 | } 110 | 111 | javadoc { 112 | options{ 113 | encoding "UTF-8" 114 | charSet 'UTF-8' 115 | author true 116 | version true 117 | links "http://docs.oracle.com/javase/7/docs/api" 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /usbserialport/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/hd/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /usbserialport/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/.DS_Store -------------------------------------------------------------------------------- /usbserialport/src/main/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/main/.DS_Store -------------------------------------------------------------------------------- /usbserialport/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /usbserialport/src/main/cpp/SerialPort.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009-2011 Cedric Priscal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "SerialPort.h" 26 | 27 | #include "android/log.h" 28 | static const char *TAG="serial_port"; 29 | #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args) 30 | #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args) 31 | #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args) 32 | 33 | static speed_t getBaudrate(jint baudrate) 34 | { 35 | switch(baudrate) { 36 | case 0: return B0; 37 | case 50: return B50; 38 | case 75: return B75; 39 | case 110: return B110; 40 | case 134: return B134; 41 | case 150: return B150; 42 | case 200: return B200; 43 | case 300: return B300; 44 | case 600: return B600; 45 | case 1200: return B1200; 46 | case 1800: return B1800; 47 | case 2400: return B2400; 48 | case 4800: return B4800; 49 | case 9600: return B9600; 50 | case 19200: return B19200; 51 | case 38400: return B38400; 52 | case 57600: return B57600; 53 | case 115200: return B115200; 54 | case 230400: return B230400; 55 | case 460800: return B460800; 56 | case 500000: return B500000; 57 | case 576000: return B576000; 58 | case 921600: return B921600; 59 | case 1000000: return B1000000; 60 | case 1152000: return B1152000; 61 | case 1500000: return B1500000; 62 | case 2000000: return B2000000; 63 | case 2500000: return B2500000; 64 | case 3000000: return B3000000; 65 | case 3500000: return B3500000; 66 | case 4000000: return B4000000; 67 | default: return -1; 68 | } 69 | } 70 | 71 | /* 72 | * Class: android_serialport_SerialPort 73 | * Method: open 74 | * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; 75 | */ 76 | JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open 77 | (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags) 78 | { 79 | int fd; 80 | speed_t speed; 81 | jobject mFileDescriptor; 82 | 83 | /* Check arguments */ 84 | { 85 | speed = getBaudrate(baudrate); 86 | if (speed == -1) { 87 | /* TODO: throw an exception */ 88 | LOGE("Invalid baudrate"); 89 | return NULL; 90 | } 91 | } 92 | 93 | /* Opening device */ 94 | { 95 | jboolean iscopy; 96 | const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy); 97 | LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags); 98 | fd = open(path_utf, O_RDWR | flags); 99 | LOGD("open() fd = %d", fd); 100 | (*env)->ReleaseStringUTFChars(env, path, path_utf); 101 | if (fd == -1) 102 | { 103 | /* Throw an exception */ 104 | LOGE("Cannot open port"); 105 | /* TODO: throw an exception */ 106 | return NULL; 107 | } 108 | } 109 | 110 | /* Configure device */ 111 | { 112 | struct termios cfg; 113 | LOGD("Configuring serial port"); 114 | if (tcgetattr(fd, &cfg)) 115 | { 116 | LOGE("tcgetattr() failed 1"); 117 | close(fd); 118 | /* TODO: throw an exception */ 119 | return NULL; 120 | } 121 | 122 | cfmakeraw(&cfg); 123 | cfsetispeed(&cfg, speed); 124 | cfsetospeed(&cfg, speed); 125 | 126 | if (tcsetattr(fd, TCSANOW, &cfg)) 127 | { 128 | LOGE("tcsetattr() failed 2"); 129 | close(fd); 130 | /* TODO: throw an exception */ 131 | return NULL; 132 | } 133 | } 134 | 135 | /* Create a corresponding file descriptor */ 136 | { 137 | jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor"); 138 | jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "", "()V"); 139 | jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I"); 140 | mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor); 141 | (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd); 142 | } 143 | 144 | return mFileDescriptor; 145 | } 146 | 147 | /* 148 | * Class: cedric_serial_SerialPort 149 | * Method: close 150 | * Signature: ()V 151 | */ 152 | JNIEXPORT void JNICALL Java_android_serialport_SerialPort_close 153 | (JNIEnv *env, jobject thiz) 154 | { 155 | jclass SerialPortClass = (*env)->GetObjectClass(env, thiz); 156 | jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor"); 157 | 158 | jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;"); 159 | jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I"); 160 | 161 | jobject mFd = (*env)->GetObjectField(env, thiz, mFdID); 162 | jint descriptor = (*env)->GetIntField(env, mFd, descriptorID); 163 | 164 | LOGD("close(fd = %d)", descriptor); 165 | close(descriptor); 166 | } 167 | 168 | -------------------------------------------------------------------------------- /usbserialport/src/main/cpp/SerialPort.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class android_serialport_SerialPort */ 4 | 5 | #ifndef _Included_android_serialport_SerialPort 6 | #define _Included_android_serialport_SerialPort 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | /* 11 | * Class: android_serialport_SerialPort 12 | * Method: open 13 | * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; 14 | */ 15 | JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open 16 | (JNIEnv *, jclass, jstring, jint, jint); 17 | 18 | /* 19 | * Class: android_serialport_SerialPort 20 | * Method: close 21 | * Signature: ()V 22 | */ 23 | JNIEXPORT void JNICALL Java_android_serialport_SerialPort_close 24 | (JNIEnv *, jobject); 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | #endif 30 | -------------------------------------------------------------------------------- /usbserialport/src/main/cpp/gen_SerialPort_h.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | javah -o SerialPort.h -jni -classpath ../java android.serialport.SerialPort 3 | 4 | -------------------------------------------------------------------------------- /usbserialport/src/main/cpp/run_emulator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | { 3 | adb wait-for-device 4 | adb shell chmod 666 /dev/ttyS2 5 | } & 6 | emulator-arm -avd Android_1.5 -qemu -serial stdio 7 | 8 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/android/serialport/SerialPort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Cedric Priscal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package android.serialport; 18 | 19 | import android.util.Log; 20 | 21 | import java.io.File; 22 | import java.io.FileDescriptor; 23 | import java.io.FileInputStream; 24 | import java.io.FileOutputStream; 25 | import java.io.IOException; 26 | import java.io.InputStream; 27 | import java.io.OutputStream; 28 | 29 | public class SerialPort { 30 | 31 | private static final String TAG = "SerialPort"; 32 | 33 | /** 34 | * Do not remove or rename the field mFd: it is used by native method close(); 35 | */ 36 | private FileDescriptor mFd; 37 | private FileInputStream mFileInputStream; 38 | private FileOutputStream mFileOutputStream; 39 | private String path; 40 | 41 | public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException { 42 | /* Check access permission */ 43 | if (!device.canRead() || !device.canWrite()) { 44 | try { 45 | /* Missing read/write permission, trying to chmod the file */ 46 | Process su; 47 | su = Runtime.getRuntime().exec("/system/bin/su"); 48 | String cmd = "chmod 666 " + device.getAbsolutePath() + "\n" + "exit\n"; 49 | su.getOutputStream().write(cmd.getBytes()); 50 | if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) { 51 | throw new SecurityException(); 52 | } 53 | Log.d(TAG,"target device missing read/write permission, trying to chmod the file"); 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | throw new SecurityException(); 57 | } 58 | } 59 | mFd = open(device.getAbsolutePath(), baudrate, flags); 60 | if (mFd == null) { 61 | Log.e(TAG, "native open returns null"); 62 | throw new IOException(); 63 | } 64 | path=device.getPath(); 65 | mFileInputStream = new FileInputStream(mFd); 66 | mFileOutputStream = new FileOutputStream(mFd); 67 | } 68 | 69 | // Getters and setters 70 | 71 | public String getPath(){return path;} 72 | 73 | public InputStream getInputStream() { 74 | return mFileInputStream; 75 | } 76 | 77 | public OutputStream getOutputStream() { 78 | return mFileOutputStream; 79 | } 80 | 81 | // JNI 82 | private native static FileDescriptor open(String path, int baudrate, int flags); 83 | 84 | public native void close(); 85 | 86 | static { 87 | System.loadLibrary("serial_port"); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/android/serialport/SerialPortFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Cedric Priscal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package android.serialport; 18 | 19 | import android.util.Log; 20 | 21 | import java.io.File; 22 | import java.io.FileReader; 23 | import java.io.IOException; 24 | import java.io.LineNumberReader; 25 | import java.util.Arrays; 26 | import java.util.Iterator; 27 | import java.util.Vector; 28 | import java.util.concurrent.ConcurrentHashMap; 29 | 30 | public class SerialPortFinder { 31 | 32 | public class Driver { 33 | Driver(String name, String root) { 34 | mDriverName = name; 35 | mDeviceRoot = root; 36 | } 37 | private String mDriverName; 38 | private String mDeviceRoot; 39 | Vector mDevices = null; 40 | Vector getDevices() { 41 | if (mDevices == null) { 42 | mDevices = new Vector<>(); 43 | String targetStr="/dev"; 44 | File dev = new File(targetStr); 45 | File[] files = dev.listFiles(); 46 | if (files != null) { 47 | Log.d("tag", "dev :" + dev + "==" + Arrays.toString(files)); 48 | for (File file : files) { 49 | if (file.getAbsolutePath().startsWith(mDeviceRoot)) { 50 | Log.d(TAG, "Found new device: " + file); 51 | mDevices.add(file); 52 | } 53 | } 54 | } else if (mDeviceRoot.startsWith(targetStr)) { 55 | File file = new File(mDeviceRoot); 56 | Log.d(TAG, "Found new device: " + file); 57 | mDevices.add(file); 58 | } 59 | } 60 | return mDevices; 61 | } 62 | public String getName() { 63 | return mDriverName; 64 | } 65 | } 66 | 67 | private static final String TAG = "SerialPort"; 68 | 69 | private Vector mDrivers = null; 70 | 71 | private Vector getDrivers() throws IOException { 72 | if (mDrivers == null) { 73 | mDrivers = new Vector<>(); 74 | LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers")); 75 | String l; 76 | while((l = r.readLine()) != null) { 77 | // Issue 3: 78 | // Since driver name may contain spaces, we do not extract driver name with split() 79 | String drivername = l.substring(0, 0x15).trim(); 80 | String[] w = l.split(" +"); 81 | Log.d("SerialPortFinder","drivername :"+drivername+"====="+l); 82 | if ((w.length >= 5) && (w[w.length-1].equals("serial"))) { 83 | Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length-4]); 84 | mDrivers.add(new Driver(drivername, w[w.length-4])); 85 | } 86 | } 87 | r.close(); 88 | } 89 | return mDrivers; 90 | } 91 | 92 | private ConcurrentHashMap findAllDevices(){ 93 | ConcurrentHashMap devices = new ConcurrentHashMap<>(); 94 | // Parse each driver 95 | Iterator itdriv; 96 | try { 97 | itdriv = getDrivers().iterator(); 98 | while(itdriv.hasNext()) { 99 | Driver driver = itdriv.next(); 100 | for (File file : driver.getDevices()) { 101 | String deviceName = file.getName(); 102 | String devicePath = file.getAbsolutePath(); 103 | deviceName = String.format("%s (%s)", deviceName, driver.getName()); 104 | Log.d("SerialPortFinder", "findAllDevices device name : " + deviceName + " , device path : " + devicePath); 105 | devices.put(deviceName, devicePath); 106 | } 107 | } 108 | } catch (IOException e) { 109 | e.printStackTrace(); 110 | } 111 | return devices; 112 | } 113 | 114 | public ConcurrentHashMap getAllDevices(){ 115 | return findAllDevices(); 116 | } 117 | 118 | public String[] getAllDevicesName() { 119 | ConcurrentHashMapallDevices=getAllDevices(); 120 | return allDevices.keySet().toArray(new String[allDevices.size()]); 121 | } 122 | 123 | public String[] getAllDevicesPath() { 124 | ConcurrentHashMapallDevices=getAllDevices(); 125 | return allDevices.values().toArray(new String[allDevices.size()]); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/config/MeasureStatus.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.config 2 | 3 | /** 4 | * Created by hd on 2017/8/22. 5 | * 6 | */ 7 | enum class MeasureStatus { 8 | PREPARE, RUNNING, READING, WRITING, WAITING, STOPPING, STOPPED 9 | } 10 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/config/UsbPortDeviceType.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.config 2 | 3 | 4 | /** 5 | * Created by hd on 2017/8/22 . 6 | * support device type 7 | */ 8 | enum class UsbPortDeviceType(var value: String? = DriversType.USB_PL2303) { 9 | USB_OTHERS, 10 | /**custom driver type*/ 11 | USB_CUSTOM_TYPE, 12 | } 13 | 14 | object DriversType { 15 | const val USB_CP21xx = "usb_cp21xx" 16 | const val USB_PL2303 = "usb_pl2303" 17 | const val USB_FTD = "usb_ftd" 18 | const val USB_CDC_ACM = "usb_cdc_acm" 19 | const val USB_CH34xx = "usb_ch34xx" 20 | } -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/engine/Engine.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.engine 2 | 3 | import android.content.Context 4 | import android.os.SystemClock 5 | import com.hd.serialport.config.MeasureStatus 6 | import com.hd.serialport.listener.SerialPortMeasureListener 7 | import com.hd.serialport.listener.UsbMeasureListener 8 | import com.hd.serialport.param.SerialPortMeasureParameter 9 | import com.hd.serialport.param.UsbMeasureParameter 10 | import com.hd.serialport.reader.ReadWriteRunnable 11 | import com.hd.serialport.usb_driver.UsbSerialPort 12 | import com.hd.serialport.utils.L 13 | import java.util.concurrent.ExecutorService 14 | import java.util.concurrent.Executors 15 | import java.util.concurrent.atomic.AtomicInteger 16 | 17 | 18 | /** 19 | * Created by hd on 2017/8/27 . 20 | * engine 21 | */ 22 | abstract class Engine(val context: Context) { 23 | 24 | private val executor: ExecutorService = Executors.newCachedThreadPool() 25 | 26 | private val defaultKey = AtomicInteger(-1) 27 | 28 | private val defaultTagPrefix = "engine_" 29 | 30 | private val runnableMap = mutableMapOf() 31 | 32 | private val tagMap = mutableMapOf() 33 | 34 | private val statusMap = mutableMapOf() 35 | 36 | private var status: MeasureStatus = MeasureStatus.PREPARE 37 | 38 | fun submit(tag: Any?, runnable: ReadWriteRunnable) { 39 | status = MeasureStatus.RUNNING 40 | defaultKey.incrementAndGet() 41 | val customTag = defaultTagPrefix + defaultKey.get().toString() 42 | runnableMap[customTag] = runnable 43 | tagMap[customTag] = tag ?: defaultTagPrefix 44 | statusMap[customTag] = status 45 | executor.submit(runnable) 46 | } 47 | 48 | fun write(tag: Any? = null, data: List?) { 49 | try { 50 | if (!data.isNullOrEmpty() && isWorking()) { 51 | tagMap.filter { tag == null || tag.toString().isEmpty() || it.value == tag }.map { runnableMap[it.key] }.forEach { runnable -> 52 | data.forEach { 53 | runnable?.write(it) 54 | SystemClock.sleep(10) 55 | } 56 | } 57 | } 58 | } catch (e: Exception) { 59 | e.printStackTrace() 60 | } 61 | } 62 | 63 | fun stop(tag: Any? = null) { 64 | L.d("Engine executor stop ?" + status + ",runnable size :" + runnableMap.size) 65 | try { 66 | if (!isWorking()) { 67 | tagMap.filter { tag == null || tag.toString().isEmpty() || it.value == tag }.map { 68 | statusMap[it.key] = MeasureStatus.STOPPED 69 | runnableMap[it.key] 70 | }.forEach { 71 | it?.stop() 72 | SystemClock.sleep(10) 73 | } 74 | status = if (statusMap.values.contains(MeasureStatus.RUNNING)) MeasureStatus.RUNNING else MeasureStatus.STOPPED 75 | } 76 | } catch (e: Exception) { 77 | e.printStackTrace() 78 | } finally { 79 | release() 80 | } 81 | } 82 | 83 | fun isWorking(): Boolean = status == MeasureStatus.RUNNING 84 | 85 | private fun release() { 86 | if (!isWorking()) { 87 | tagMap.clear() 88 | statusMap.clear() 89 | runnableMap.clear() 90 | defaultKey.set(-1) 91 | status = MeasureStatus.PREPARE 92 | } 93 | } 94 | 95 | open fun open(usbSerialPort: UsbSerialPort, parameter: UsbMeasureParameter, measureListener: UsbMeasureListener) {} 96 | 97 | open fun open(parameter: SerialPortMeasureParameter, measureListener: SerialPortMeasureListener) {} 98 | 99 | } 100 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/engine/SerialPortEngine.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.engine 2 | 3 | import android.content.Context 4 | import android.serialport.SerialPort 5 | import com.hd.serialport.R 6 | import com.hd.serialport.listener.SerialPortMeasureListener 7 | import com.hd.serialport.param.SerialPortMeasureParameter 8 | import com.hd.serialport.reader.SerialPortReadWriteRunnable 9 | import java.io.File 10 | import java.io.IOException 11 | import java.security.InvalidParameterException 12 | 13 | 14 | /** 15 | * Created by hd on 2017/8/27 . 16 | * serial-port engine 17 | */ 18 | class SerialPortEngine(context: Context) : Engine(context) { 19 | 20 | override fun open(parameter: SerialPortMeasureParameter, measureListener: SerialPortMeasureListener) { 21 | super.open(parameter, measureListener) 22 | try { 23 | if (parameter.devicePath.isNullOrEmpty()) { 24 | measureListener.measureError(parameter.tag, context.resources.getString(R.string.error_configuration)) 25 | } else { 26 | val serialPort = SerialPort(File(parameter.devicePath!!), parameter.baudRate, parameter.flags) 27 | val serialPortReadWriteRunnable = SerialPortReadWriteRunnable(parameter.devicePath!!, serialPort, measureListener, this, parameter.tag) 28 | submit(parameter.tag, serialPortReadWriteRunnable) 29 | } 30 | } catch (e: SecurityException) { 31 | measureListener.measureError(parameter.tag, context.resources.getString(R.string.error_security)) 32 | } catch (e: IOException) { 33 | measureListener.measureError(parameter.tag, context.resources.getString(R.string.error_unknown)) 34 | } catch (e: InvalidParameterException) { 35 | measureListener.measureError(parameter.tag, context.resources.getString(R.string.error_configuration)) 36 | } finally { 37 | stop(parameter.tag) 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/engine/UsbPortEngine.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.engine 2 | 3 | import android.content.Context 4 | import android.hardware.usb.UsbManager 5 | import com.hd.serialport.R 6 | import com.hd.serialport.help.RequestUsbPermission 7 | import com.hd.serialport.listener.UsbMeasureListener 8 | import com.hd.serialport.param.UsbMeasureParameter 9 | import com.hd.serialport.reader.UsbReadWriteRunnable 10 | import com.hd.serialport.usb_driver.UsbSerialPort 11 | import com.hd.serialport.utils.L 12 | 13 | /** 14 | * Created by hd on 2017/8/22 . 15 | * usb-port engine 16 | */ 17 | class UsbPortEngine(context: Context, private val usbManager: UsbManager) : Engine(context) { 18 | 19 | override fun open(usbSerialPort: UsbSerialPort, parameter: UsbMeasureParameter, 20 | measureListener: UsbMeasureListener) { 21 | super.open(usbSerialPort, parameter, measureListener) 22 | try { 23 | val usbDevice = usbSerialPort.driver.device 24 | if (!RequestUsbPermission.newInstance().requestUsbPermission(context, usbManager, usbDevice)) { 25 | L.e("request usb permission failed :$usbDevice") 26 | } else { 27 | val connection = usbManager.openDevice(usbDevice) 28 | if (connection != null) { 29 | usbSerialPort.open(connection) 30 | usbSerialPort.setParameters(parameter.baudRate, parameter.dataBits, parameter.stopBits, parameter.parity) 31 | val usbReadWriteRunnable = UsbReadWriteRunnable(usbSerialPort, measureListener, this, parameter.tag) 32 | submit(parameter.tag, usbReadWriteRunnable) 33 | L.d("open usb device success") 34 | } else { 35 | L.d("open device failure,connection is null") 36 | measureListener.measureError(parameter.tag, context.resources.getString(R.string.open_target_device_error)) 37 | } 38 | } 39 | } catch (ignored: Exception) { 40 | L.e("open device failure :$ignored") 41 | measureListener.measureError(parameter.tag, context.resources.getString(R.string.open_target_device_error)) 42 | } finally { 43 | stop(parameter.tag) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/help/RequestPermissionBroadCastReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.help 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.hardware.usb.UsbDevice 7 | import android.hardware.usb.UsbManager 8 | import com.hd.serialport.utils.L 9 | 10 | /** 11 | * Created by hd on 2017/8/22. 12 | * request permission at midway equipment access 13 | */ 14 | class RequestPermissionBroadCastReceiver : BroadcastReceiver() { 15 | 16 | override fun onReceive(context: Context, intent: Intent) { 17 | when (intent.action) { 18 | UsbManager.ACTION_USB_DEVICE_ATTACHED -> { 19 | val usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) 20 | L.d("Note: midway equipment access ===> $usbDevice") 21 | } 22 | UsbManager.ACTION_USB_DEVICE_DETACHED -> L.d("Note: there is a device to be removed!") 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/help/RequestUsbPermission.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.help 2 | 3 | import android.annotation.SuppressLint 4 | import android.app.PendingIntent 5 | import android.content.BroadcastReceiver 6 | import android.content.Context 7 | import android.content.Intent 8 | import android.content.IntentFilter 9 | import android.hardware.usb.UsbDevice 10 | import android.hardware.usb.UsbManager 11 | import android.os.AsyncTask 12 | import com.hd.serialport.utils.L 13 | import java.util.* 14 | 15 | /** 16 | * Created by hd on 2017/8/22. 17 | * request the usb permissions at the terminal device. 18 | */ 19 | class RequestUsbPermission { 20 | private val usb_permission = "com.hd.usbHost.device.USB_PERMISSION" 21 | private var usbDeviceList: MutableList? = null 22 | private var position = 0 23 | private var usbManager: UsbManager? = null 24 | private var callback: RequestPermissionCallback? = null 25 | 26 | interface RequestPermissionCallback { 27 | 28 | /** 29 | * all usb permission request complete 30 | */ 31 | fun complete() 32 | 33 | /** 34 | * may not have device 35 | */ 36 | fun failed() 37 | } 38 | 39 | fun requestUsbPermission(context: Context, usbManager: UsbManager?, device: UsbDevice?): Boolean { 40 | this.usbManager = usbManager 41 | if (device == null) 42 | return false 43 | if (this.usbManager == null) 44 | this.usbManager = getUsbManager(context) 45 | if (!this.usbManager!!.hasPermission(device)) { 46 | this.usbManager!!.requestPermission(device, getPendingIntent(context, device)) 47 | return this.usbManager!!.hasPermission(device) 48 | } 49 | return true 50 | } 51 | 52 | fun requestAllUsbDevicePermission(context: Context, callback: RequestPermissionCallback?=null) { 53 | this.callback = callback 54 | requestAllUsbDevicePermission(context) 55 | } 56 | 57 | private fun requestAllUsbDevicePermission(context: Context) { 58 | asyncRequestAllUsbDevicePermission(context) 59 | } 60 | 61 | @SuppressLint("StaticFieldLeak") 62 | private fun asyncRequestAllUsbDevicePermission(context: Context) { 63 | object : AsyncTask() { 64 | override fun doInBackground(vararg voids: Void): Void? { 65 | RootCmd.execRootCmdOrder()//execute root order 66 | val usbManager = getUsbManager(context) 67 | usbDeviceList = LinkedList() 68 | usbDeviceList!!.addAll(usbManager.deviceList.values) 69 | position = 0 70 | if (usbDeviceList!!.size > 0) { 71 | request(context, usbManager, usbDeviceList!![position]) 72 | } else { 73 | callback?.failed() 74 | } 75 | return null 76 | } 77 | }.execute() 78 | } 79 | 80 | private fun getUsbManager(context: Context): UsbManager { 81 | return context.getSystemService(Context.USB_SERVICE) as UsbManager 82 | } 83 | 84 | private fun getPendingIntent(context: Context, device: UsbDevice?): PendingIntent { 85 | return PendingIntent.getBroadcast(context.applicationContext, 86 | device?.hashCode() ?: 0, Intent(usb_permission), PendingIntent.FLAG_UPDATE_CURRENT) 87 | } 88 | 89 | private fun request(context: Context, usbManager: UsbManager, usbDevice: UsbDevice) { 90 | if (!usbManager.hasPermission(usbDevice)) { 91 | intent = context.registerReceiver(usbBroadCastReceiver, IntentFilter(usb_permission)) 92 | usbManager.requestPermission(usbDevice, getPendingIntent(context, usbDevice)) 93 | } else { 94 | L.d("current usb device has permission") 95 | requestContinue(context, usbManager) 96 | } 97 | } 98 | 99 | private var intent: Intent? = null 100 | 101 | private fun requestContinue(context: Context, usbManager: UsbManager) { 102 | position++ 103 | if (position < usbDeviceList!!.size) { 104 | request(context, usbManager, usbDeviceList!![position]) 105 | } else { 106 | if (intent != null) { 107 | usbBroadCastReceiver.abortBroadcast() 108 | context.unregisterReceiver(usbBroadCastReceiver) 109 | } 110 | callback?.complete() 111 | } 112 | } 113 | 114 | private val usbBroadCastReceiver = object : BroadcastReceiver() { 115 | override fun onReceive(context: Context, intent: Intent) { 116 | when (intent.action) { 117 | usb_permission -> { 118 | val device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) 119 | val success = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) 120 | L.d("permission response :" + device.hashCode() + "===" + success + "===" + device) 121 | requestContinue(context, getUsbManager(context)) 122 | } 123 | } 124 | } 125 | } 126 | 127 | companion object { 128 | 129 | fun newInstance(): RequestUsbPermission { 130 | return RequestUsbPermission() 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/help/RootCmd.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.help 2 | 3 | 4 | /** 5 | * Created by hd on 2017/8/22. 6 | * 执行Linux命令,修改usb权限为可读 7 | */ 8 | object RootCmd { 9 | 10 | // 开放/dev目录下所有文件的读、写、执行权限, " -R " 指令勿随意指定,较危险操作; 11 | // 其他指令例如下 : 12 | //

13 | // "chmod 777 /dev;" 14 | // + "chmod 777 /dev/;" 15 | // + "chmod 777 /dev/usb/;" 16 | // + "chmod 777 /dev/bus/;" 17 | // + "chmod 777 /dev/bus/usb/;" 18 | // + "chmod 777 /dev/bus/usb/0*;" 19 | // + "chmod 777 /dev/bus/usb/001/*;" 20 | // + "chmod 777 /dev/bus/usb/002/*;" 21 | // + "chmod 777 /dev/bus/usb/003/*;" 22 | // + "chmod 777 /dev/bus/usb/004/*;" 23 | // + "chmod 777 /dev/bus/usb/005/*;" 24 | private val param_all = "chmod 777 /dev;" + "chmod -R 777 /dev/*" 25 | 26 | @JvmOverloads fun execRootCmdOrder(paramString: String = param_all): Int { 27 | try { 28 | val su = Runtime.getRuntime().exec("/system/bin/su") 29 | su.outputStream.write(paramString.toByteArray()) 30 | su.outputStream.flush() 31 | su.outputStream.write("\nexit\n".toByteArray()) 32 | su.outputStream.flush() 33 | su.waitFor() 34 | return su.exitValue() 35 | } catch (localException: Exception) { 36 | localException.printStackTrace() 37 | } 38 | return 0 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/help/SystemSecurity.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.help 2 | 3 | import android.content.Context 4 | import android.hardware.usb.UsbDevice 5 | import android.hardware.usb.UsbManager 6 | import com.hd.serialport.utils.L 7 | 8 | /** 9 | * Created by hd on 2017/8/22. 10 | * 11 | * some vendors provide SDK maybe exists error in the usb module. 12 | * 13 | * the error come from the API [UsbDevice.getInterface] and belongs to the system SDK error, 14 | * might throw a error [NullPointerException] after when you traverse all usb and call it. 15 | * 16 | * this error need the vendors to modify the underlying code, 17 | * however,in fact, we can also go to avoid it by use API[UsbDevice.getInterfaceCount] to judge, 18 | * but,in order to avoid other unknown problems to modify the underlying code is the best way. 19 | * 20 | * in theory, you only need to check once,so ,advice used that in project debugging or test project. 21 | */ 22 | object SystemSecurity { 23 | 24 | /** 25 | * @return return true if the current system security's support usb devices 26 | */ 27 | fun check(context: Context): Boolean { 28 | return try { 29 | val usbManager = context.applicationContext.getSystemService(Context.USB_SERVICE) as UsbManager 30 | val deviceList = usbManager.deviceList 31 | for (usbDevice in deviceList.values) 32 | usbDevice.getInterface(0) 33 | true 34 | } catch (e: Exception) { 35 | L.d("TAG", "There are errors in the current system usb module :$e") 36 | false 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/listener/MeasureListener.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.listener 2 | 3 | 4 | /** 5 | * Created by hd on 2017/8/22 . 6 | * 7 | */ 8 | interface MeasureListener { 9 | 10 | /** 11 | * hint measure error message 12 | * @param tag [com.hd.serialport.param.SerialPortMeasureParameter.tag] 13 | */ 14 | fun measureError(tag: Any?, message: String) 15 | 16 | } 17 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/listener/SerialPortMeasureListener.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.listener 2 | 3 | import java.io.OutputStream 4 | 5 | 6 | /** 7 | * Created by hd on 2017/8/27 . 8 | * 9 | */ 10 | interface SerialPortMeasureListener : MeasureListener { 11 | /** 12 | * receive data from serial port 13 | * @param path serial port device path[com.hd.serialport.param.SerialPortMeasureParameter.devicePath] 14 | * @param tag [com.hd.serialport.param.SerialPortMeasureParameter.tag] 15 | */ 16 | fun measuring(tag: Any?, path: String, data: ByteArray) 17 | 18 | /** 19 | * only initialize one time,write data into serial port [OutputStream.write] 20 | * @param tag [com.hd.serialport.param.SerialPortMeasureParameter.tag] 21 | */ 22 | fun write(tag: Any?, outputStream: OutputStream) 23 | 24 | } -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/listener/UsbMeasureListener.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.listener 2 | 3 | import com.hd.serialport.usb_driver.UsbSerialPort 4 | 5 | /** 6 | * Created by hd on 2017/8/27 . 7 | 8 | */ 9 | interface UsbMeasureListener : MeasureListener { 10 | 11 | /** 12 | * receive data[data] from usb port[usbSerialPort] 13 | * @param tag [com.hd.serialport.param.SerialPortMeasureParameter.tag] 14 | */ 15 | fun measuring(tag: Any?, usbSerialPort: UsbSerialPort, data: ByteArray) 16 | 17 | /** 18 | * only initialize one time,write data into usb port [UsbSerialPort.write] 19 | * @param tag [com.hd.serialport.param.SerialPortMeasureParameter.tag] 20 | */ 21 | fun write(tag: Any?, usbSerialPort: UsbSerialPort) 22 | } 23 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/method/DeviceMeasureController.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.method 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.hardware.usb.UsbDevice 6 | import android.hardware.usb.UsbManager 7 | import android.serialport.SerialPortFinder 8 | import com.hd.serialport.config.UsbPortDeviceType 9 | import com.hd.serialport.engine.SerialPortEngine 10 | import com.hd.serialport.engine.UsbPortEngine 11 | import com.hd.serialport.help.RequestUsbPermission 12 | import com.hd.serialport.help.SystemSecurity 13 | import com.hd.serialport.listener.SerialPortMeasureListener 14 | import com.hd.serialport.listener.UsbMeasureListener 15 | import com.hd.serialport.param.SerialPortMeasureParameter 16 | import com.hd.serialport.param.UsbMeasureParameter 17 | import com.hd.serialport.usb_driver.UsbSerialDriver 18 | import com.hd.serialport.usb_driver.UsbSerialPort 19 | import com.hd.serialport.usb_driver.UsbSerialProber 20 | import com.hd.serialport.utils.L 21 | import java.util.concurrent.ConcurrentHashMap 22 | 23 | /** 24 | * Created by hd on 2017/8/22 . 25 | * usb device measurement controller 26 | */ 27 | @SuppressLint("StaticFieldLeak") 28 | object DeviceMeasureController { 29 | 30 | private lateinit var usbManager: UsbManager 31 | 32 | private lateinit var usbPortEngine: UsbPortEngine 33 | 34 | private lateinit var serialPortEngine: SerialPortEngine 35 | 36 | fun init(context: Context, openLog: Boolean) { 37 | init(context, openLog, null) 38 | } 39 | 40 | fun init(context: Context, openLog: Boolean, callback: RequestUsbPermission.RequestPermissionCallback? = null) { 41 | init(context, openLog, true, callback) 42 | } 43 | 44 | fun init(context: Context, openLog: Boolean, requestUsbPermission: Boolean, callback: RequestUsbPermission.RequestPermissionCallback? = null) { 45 | if (!SystemSecurity.check(context)) throw RuntimeException("There are a error in the current system usb module !") 46 | L.allowLog = openLog 47 | this.usbManager = context.applicationContext.getSystemService(Context.USB_SERVICE) as UsbManager 48 | serialPortEngine = SerialPortEngine(context.applicationContext) 49 | usbPortEngine = UsbPortEngine(context.applicationContext, usbManager) 50 | if (requestUsbPermission) 51 | RequestUsbPermission.newInstance().requestAllUsbDevicePermission(context.applicationContext, callback) 52 | } 53 | 54 | fun scanUsbPort(): List = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager) 55 | 56 | fun scanSerialPort(): ConcurrentHashMap = SerialPortFinder().allDevices 57 | 58 | fun measure(usbDevice: UsbDevice, deviceType: UsbPortDeviceType, parameter: UsbMeasureParameter, listener: UsbMeasureListener) { 59 | val driver = UsbSerialProber.getDefaultProber().convertDriver(usbDevice,deviceType.value) 60 | measure(driver.ports[0], parameter, listener) 61 | } 62 | 63 | fun measure(usbSerialDriverList: List?, parameter: UsbMeasureParameter, listener: UsbMeasureListener) { 64 | if (!usbSerialDriverList.isNullOrEmpty()) { 65 | usbSerialDriverList.filter { it.deviceType == parameter.usbPortDeviceType || parameter.usbPortDeviceType == UsbPortDeviceType.USB_OTHERS } 66 | .filter { it.ports[0] != null }.forEach { measure(it.ports[0], parameter, listener) } 67 | } else { 68 | val portList = scanUsbPort() 69 | if (portList.isNullOrEmpty()) { 70 | measure(portList, parameter, listener) 71 | } else { 72 | listener.measureError(parameter.tag,"not find ports") 73 | } 74 | } 75 | } 76 | 77 | fun measure(usbSerialPort: UsbSerialPort?, parameter: UsbMeasureParameter, listener: UsbMeasureListener) { 78 | if (null != usbSerialPort) { 79 | usbPortEngine.open(usbSerialPort, parameter, listener) 80 | } else { 81 | measure(usbSerialDriverList = null, parameter = parameter, listener = listener) 82 | } 83 | } 84 | 85 | fun measure(paths: Array?, parameter: SerialPortMeasureParameter, listeners: List) { 86 | if (!paths.isNullOrEmpty()) { 87 | for (index in paths.indices) { 88 | val path = paths[index] 89 | when { 90 | path.isNotEmpty() -> { 91 | parameter.devicePath = path 92 | when { 93 | listeners.size == paths.size -> measure(parameter, listeners[index]) 94 | listeners.isNotEmpty() -> measure(parameter, listeners[0]) 95 | else -> L.d("not find serialPortMeasureListener") 96 | } 97 | } 98 | index < listeners.size -> listeners[index].measureError(parameter.tag,"path is null") 99 | else -> L.d("current position $index path is empty :$path ") 100 | } 101 | } 102 | } else { 103 | measure(SerialPortFinder().allDevicesPath, parameter, listeners) 104 | } 105 | } 106 | 107 | fun measure(parameter: SerialPortMeasureParameter, listener: SerialPortMeasureListener) { 108 | if (!parameter.devicePath.isNullOrEmpty()) { 109 | serialPortEngine.open(parameter, listener) 110 | } else { 111 | measure(paths = null, parameter = parameter, listeners = listOf(listener)) 112 | } 113 | } 114 | 115 | /**write data by the tag filter, write all if tag==null*/ 116 | fun write(data: List?, tag: Any? = null) { 117 | L.d("DeviceMeasureController write usbPortEngine is working ${usbPortEngine.isWorking()}," + 118 | "serialPortEngine is working ${serialPortEngine.isWorking()}") 119 | when { 120 | usbPortEngine.isWorking() -> usbPortEngine.write(tag, data) 121 | serialPortEngine.isWorking() -> serialPortEngine.write(tag, data) 122 | } 123 | } 124 | 125 | /**stop engine by the tag filter, stop all if tag==null*/ 126 | fun stop(tag: Any? = null) { 127 | L.d("DeviceMeasureController stop") 128 | when { 129 | usbPortEngine.isWorking() -> usbPortEngine.stop(tag) 130 | serialPortEngine.isWorking() -> serialPortEngine.stop(tag) 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/param/MeasureParameter.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.param 2 | 3 | import java.io.Serializable 4 | 5 | 6 | /** 7 | * Created by hd on 2017/8/28 . 8 | * 9 | */ 10 | abstract class MeasureParameter : Serializable -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/param/SerialPortMeasureParameter.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.param 2 | 3 | 4 | /** 5 | * Created by hd on 2017/8/27 . 6 | * @param devicePath serial port path [android.serialport.SerialPortFinder.getAllDevicesPath] 7 | * @param baudRate baud rate as an integer, for example {@code 115200}. 8 | * @param flags default value :0 9 | * @param tag set tag 10 | */ 11 | data class SerialPortMeasureParameter(var devicePath: String? = null, var baudRate: Int = 115200, 12 | var flags: Int = 0, var tag :Any?="default_serial_tag"):MeasureParameter() -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/param/UsbMeasureParameter.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.param 2 | 3 | import com.hd.serialport.config.UsbPortDeviceType 4 | 5 | 6 | /** 7 | * Created by hd on 2017/8/22 . 8 | * Sets various serial port parameters. 9 | * @param usbPortDeviceType set usb type [UsbPortDeviceType] 10 | * @param baudRate baud rate as an integer, for example {@code 115200}. 11 | * @param dataBits one of {@link UsbSerialPort#DATABITS_5}, {@link UsbSerialPort#DATABITS_6}, 12 | * {@link UsbSerialPort#DATABITS_7}, or {@link UsbSerialPort#DATABITS_8}. 13 | * @param stopBits one of {@link UsbSerialPort#STOPBITS_1}, {@link UsbSerialPort#STOPBITS_1_5}, or 14 | * {@link UsbSerialPort#STOPBITS_2}. 15 | * @param parity one of {@link UsbSerialPort#PARITY_NONE}, {@link UsbSerialPort#PARITY_ODD}, 16 | * {@link UsbSerialPort#PARITY_EVEN}, {@link UsbSerialPort#PARITY_MARK}, or 17 | * {@link UsbSerialPort#PARITY_SPACE}. 18 | * @param tag set tag 19 | */ 20 | data class UsbMeasureParameter(var usbPortDeviceType: UsbPortDeviceType?=UsbPortDeviceType.USB_OTHERS, 21 | var baudRate: Int = 115200, var dataBits: Int = 8, var stopBits: Int = 1, 22 | var parity: Int = 0,var tag : Any?="default_usb_tag"):MeasureParameter() -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/reader/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/main/java/com/hd/serialport/reader/.DS_Store -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/reader/ReadWriteRunnable.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.reader 2 | 3 | import android.content.Context 4 | import com.hd.serialport.R 5 | import com.hd.serialport.config.MeasureStatus 6 | import com.hd.serialport.listener.MeasureListener 7 | import com.hd.serialport.utils.L 8 | import java.nio.ByteBuffer 9 | 10 | 11 | /** 12 | * Created by hd on 2017/8/27 . 13 | * 14 | */ 15 | abstract class ReadWriteRunnable(val tag: Any?, val context: Context, val measureListener: MeasureListener) : Runnable { 16 | 17 | private val MAX_BUFFER_SIZE = 16 * 4096 18 | 19 | protected val READ_WAIT_MILLIS = 100 20 | 21 | private var status = MeasureStatus.PREPARE 22 | 23 | protected val readBuffer = ByteBuffer.allocate(MAX_BUFFER_SIZE)!! 24 | 25 | private val writeBuffer = ByteBuffer.allocate(MAX_BUFFER_SIZE)!! 26 | 27 | init { 28 | status = MeasureStatus.RUNNING 29 | } 30 | 31 | /** 32 | * allow write data into port,it`s recommended async write to use 33 | * [com.hd.serialport.listener.SerialPortMeasureListener.write] or 34 | * [com.hd.serialport.listener.UsbMeasureListener.write] 35 | * at write large data volumes 36 | **/ 37 | fun write(data: ByteArray) { 38 | synchronized(writeBuffer) { 39 | writeBuffer.put(data) 40 | } 41 | } 42 | 43 | fun stop() { 44 | L.d("read-write runnable stop 1 :$status") 45 | if (status != MeasureStatus.STOPPED || status != MeasureStatus.STOPPING) { 46 | status = MeasureStatus.STOPPING 47 | readBuffer.clear() 48 | writeBuffer.clear() 49 | close() 50 | status = MeasureStatus.STOPPED 51 | L.d("read-write runnable stop 2 :$status") 52 | } 53 | } 54 | 55 | abstract fun writing(byteArray: ByteArray) 56 | 57 | abstract fun reading() 58 | 59 | abstract fun close() 60 | 61 | override fun run() { 62 | while (status != MeasureStatus.STOPPED) { 63 | try { 64 | reading() 65 | } catch (ignored: Exception) { 66 | L.d("reading into port error :$ignored") 67 | measureListener.measureError(tag, context.resources.getString(R.string.measure_target_device_error)) 68 | try { 69 | close() 70 | } catch (ignored: Exception) { 71 | L.d("close error :$ignored") 72 | } 73 | status = MeasureStatus.STOPPED 74 | break 75 | } 76 | try { 77 | writing() 78 | } catch (ignored: Exception) { 79 | L.d("writing into port error:$ignored") 80 | } 81 | } 82 | } 83 | 84 | private fun writing() { 85 | synchronized(writeBuffer) { 86 | val len = writeBuffer.position() 87 | if (len > 0) { 88 | val outBuff = ByteArray(len) 89 | writeBuffer.rewind() 90 | writeBuffer.get(outBuff, 0, len) 91 | writeBuffer.clear() 92 | writing(outBuff) 93 | } 94 | } 95 | } 96 | 97 | } -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/reader/SerialPortReadWriteRunnable.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.reader 2 | 3 | import android.serialport.SerialPort 4 | import com.hd.serialport.engine.SerialPortEngine 5 | import com.hd.serialport.listener.SerialPortMeasureListener 6 | 7 | 8 | /** 9 | * Created by hd on 2017/8/27 . 10 | * 11 | */ 12 | class SerialPortReadWriteRunnable(private val devicePath: String, private val serialPort: SerialPort, 13 | listener: SerialPortMeasureListener, engine: SerialPortEngine, tag: Any?) : 14 | ReadWriteRunnable(tag, engine.context, listener) { 15 | init { 16 | (measureListener as SerialPortMeasureListener).write(tag, serialPort.outputStream!!) 17 | } 18 | 19 | override fun writing(byteArray: ByteArray) { 20 | serialPort.outputStream?.write(byteArray) 21 | } 22 | 23 | override fun reading() { 24 | var length = serialPort.inputStream?.available() ?: 0 25 | if (length > 0) { 26 | length = serialPort.inputStream!!.read(readBuffer.array()) 27 | val data = ByteArray(length) 28 | readBuffer.get(data, 0, length) 29 | (measureListener as SerialPortMeasureListener).measuring(tag, devicePath, data) 30 | readBuffer.clear() 31 | } 32 | } 33 | 34 | override fun close() { 35 | try { 36 | serialPort.close() 37 | } catch (e: Exception) { 38 | e.printStackTrace() 39 | } finally { 40 | try { 41 | serialPort.outputStream?.close() 42 | } catch (e: Exception) { 43 | e.printStackTrace() 44 | } 45 | try { 46 | serialPort.inputStream?.close() 47 | } catch (e: Exception) { 48 | e.printStackTrace() 49 | } 50 | } 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/reader/UsbReadWriteRunnable.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.reader 2 | 3 | import com.hd.serialport.config.UsbPortDeviceType 4 | import com.hd.serialport.engine.UsbPortEngine 5 | import com.hd.serialport.listener.UsbMeasureListener 6 | import com.hd.serialport.usb_driver.UsbSerialPort 7 | 8 | 9 | /** 10 | * Created by hd on 2017/8/27 . 11 | * 12 | */ 13 | class UsbReadWriteRunnable(private val usbSerialPort: UsbSerialPort, 14 | listener: UsbMeasureListener, engine: UsbPortEngine, tag: Any?) : 15 | ReadWriteRunnable(tag, engine.context, listener) { 16 | init { 17 | listener.write(tag, usbSerialPort) 18 | } 19 | 20 | override fun writing(byteArray: ByteArray) { 21 | usbSerialPort.write(byteArray, READ_WAIT_MILLIS * 10) 22 | } 23 | 24 | override fun reading() { 25 | val length = usbSerialPort.read(readBuffer.array(), READ_WAIT_MILLIS) 26 | if (length > 0) { 27 | val data = ByteArray(length) 28 | readBuffer.get(data, 0, length) 29 | (measureListener as UsbMeasureListener).measuring(tag, usbSerialPort, data) 30 | } 31 | readBuffer.clear() 32 | } 33 | 34 | override fun close() { 35 | try { 36 | usbSerialPort.close() 37 | } catch (e: Exception) { 38 | e.printStackTrace() 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/usb_driver/CommonUsbSerialDriver.java: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.usb_driver; 2 | 3 | import android.hardware.usb.UsbDevice; 4 | import android.support.annotation.Keep; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.hd.serialport.config.UsbPortDeviceType; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by hd on 2017/2/27 0027. 14 | */ 15 | @Keep 16 | public abstract class CommonUsbSerialDriver implements UsbSerialDriver { 17 | 18 | public UsbDevice mDevice; 19 | 20 | public UsbSerialPort mPort; 21 | 22 | public abstract UsbSerialPort setPort(UsbDevice mDevice); 23 | 24 | @NonNull 25 | public abstract String setDriverName(); 26 | 27 | public CommonUsbSerialDriver(UsbDevice mDevice) { 28 | this.mDevice = mDevice; 29 | mPort = setPort(mDevice); 30 | } 31 | 32 | @Override 33 | public UsbDevice getDevice() { 34 | return mDevice; 35 | } 36 | 37 | @Override 38 | public List getPorts() { 39 | return Collections.singletonList(mPort); 40 | } 41 | 42 | @Override 43 | public UsbPortDeviceType getDeviceType() { 44 | UsbPortDeviceType type = UsbPortDeviceType.USB_CUSTOM_TYPE; 45 | type.setValue(setDriverName()); 46 | return type; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/usb_driver/CommonUsbSerialPort.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2011-2013 Google Inc. 2 | * Copyright 2013 mike wakerly 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 | * USA. 18 | * 19 | * Project home page: https://github.com/mik3y/usb-serial-for-android 20 | */ 21 | 22 | package com.hd.serialport.usb_driver; 23 | 24 | import android.hardware.usb.UsbDevice; 25 | import android.hardware.usb.UsbDeviceConnection; 26 | 27 | 28 | import java.io.IOException; 29 | 30 | /** 31 | * A base class shared by several driver implementations. 32 | * 33 | * @author mike wakerly (opensource@hoho.com) 34 | */ 35 | public abstract class CommonUsbSerialPort implements UsbSerialPort { 36 | 37 | public static final int DEFAULT_READ_BUFFER_SIZE = 16 * 1024; 38 | public static final int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024; 39 | 40 | protected final UsbDevice mDevice; 41 | protected final int mPortNumber; 42 | 43 | // non-null when open() 44 | protected UsbDeviceConnection mConnection = null; 45 | 46 | protected final Object mReadBufferLock = new Object(); 47 | protected final Object mWriteBufferLock = new Object(); 48 | 49 | /** 50 | * Internal read buffer. Guarded by {@link #mReadBufferLock}. 51 | */ 52 | protected byte[] mReadBuffer; 53 | 54 | /** 55 | * Internal write buffer. Guarded by {@link #mWriteBufferLock}. 56 | */ 57 | protected byte[] mWriteBuffer; 58 | 59 | public CommonUsbSerialPort(UsbDevice device, int portNumber) { 60 | mDevice = device; 61 | mPortNumber = portNumber; 62 | 63 | mReadBuffer = new byte[DEFAULT_READ_BUFFER_SIZE]; 64 | mWriteBuffer = new byte[DEFAULT_WRITE_BUFFER_SIZE]; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return String.format("<%s device_name=%s device_id=%s port_number=%s>", getClass().getSimpleName(), mDevice.getDeviceName(), mDevice.getDeviceId(), mPortNumber); 70 | } 71 | 72 | @Override 73 | public UsbDeviceConnection getUsbDeviceConnection() { 74 | return mConnection; 75 | } 76 | 77 | /** 78 | * Returns the currently-bound USB device. 79 | * 80 | * @return the device 81 | */ 82 | public final UsbDevice getDevice() { 83 | return mDevice; 84 | } 85 | 86 | @Override 87 | public int getPortNumber() { 88 | return mPortNumber; 89 | } 90 | 91 | /** 92 | * Returns the device serial number 93 | * 94 | * @return serial number 95 | */ 96 | @Override 97 | public String getSerial() { 98 | return mConnection.getSerial(); 99 | } 100 | 101 | @Override 102 | public boolean purgeHwBuffers(boolean flushReadBuffers, boolean flushWriteBuffers) throws IOException { 103 | return !flushReadBuffers && !flushWriteBuffers; 104 | } 105 | 106 | /** 107 | * Sets the size of the internal buffer used to exchange data with the USB 108 | * stack for read operations. Most users should not need to change this. 109 | * 110 | * @param bufferSize the size in bytes 111 | */ 112 | public final void setReadBufferSize(int bufferSize) { 113 | synchronized (mReadBufferLock) { 114 | if (bufferSize == mReadBuffer.length) { 115 | return; 116 | } 117 | mReadBuffer = new byte[bufferSize]; 118 | } 119 | } 120 | 121 | /** 122 | * Sets the size of the internal buffer used to exchange data with the USB 123 | * stack for write operations. Most users should not need to change this. 124 | * 125 | * @param bufferSize the size in bytes 126 | */ 127 | public final void setWriteBufferSize(int bufferSize) { 128 | synchronized (mWriteBufferLock) { 129 | if (bufferSize == mWriteBuffer.length) { 130 | return; 131 | } 132 | mWriteBuffer = new byte[bufferSize]; 133 | } 134 | } 135 | 136 | @Override 137 | public abstract void open(UsbDeviceConnection connection) throws IOException; 138 | 139 | @Override 140 | public abstract void close() throws IOException; 141 | 142 | @Override 143 | public abstract int read(final byte[] dest, final int timeoutMillis) throws IOException; 144 | 145 | @Override 146 | public abstract int write(final byte[] src, final int timeoutMillis) throws IOException; 147 | 148 | @Override 149 | public abstract void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException; 150 | 151 | @Override 152 | public abstract boolean getCD() throws IOException; 153 | 154 | @Override 155 | public abstract boolean getCTS() throws IOException; 156 | 157 | @Override 158 | public abstract boolean getDSR() throws IOException; 159 | 160 | @Override 161 | public abstract boolean getDTR() throws IOException; 162 | 163 | @Override 164 | public abstract void setDTR(boolean value) throws IOException; 165 | 166 | @Override 167 | public abstract boolean getRI() throws IOException; 168 | 169 | @Override 170 | public abstract boolean getRTS() throws IOException; 171 | 172 | @Override 173 | public abstract void setRTS(boolean value) throws IOException; 174 | 175 | } 176 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/usb_driver/ProbeTable.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2011-2013 Google Inc. 2 | * Copyright 2013 mike wakerly 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 | * USA. 18 | * 19 | * Project home page: https://github.com/mik3y/usb-serial-for-android 20 | */ 21 | 22 | package com.hd.serialport.usb_driver; 23 | 24 | import android.util.Pair; 25 | 26 | import java.lang.reflect.InvocationTargetException; 27 | import java.lang.reflect.Method; 28 | import java.util.LinkedHashMap; 29 | import java.util.Map; 30 | 31 | /** 32 | * Maps (vendor id, product id) pairs to the corresponding serial driver. 33 | * 34 | * @author mike wakerly (opensource@hoho.com) 35 | */ 36 | public class ProbeTable { 37 | 38 | private final Map, Class> mProbeTable =new LinkedHashMap, Class>(); 39 | 40 | public Map, Class> getProbeTable(){ 41 | return mProbeTable; 42 | } 43 | /** 44 | * Adds or updates a (vendor, product) pair in the table. 45 | * 46 | * @param vendorId the USB vendor id 47 | * @param productId the USB product id 48 | * @param driverClass the driver class responsible for this pair 49 | * @return {@code this}, for chaining 50 | */ 51 | public ProbeTable addProduct(int vendorId, int productId, Class driverClass) { 52 | mProbeTable.put(Pair.create(vendorId, productId), driverClass); 53 | return this; 54 | } 55 | 56 | /** 57 | * Internal method to add all supported products from 58 | * {@code getSupportedProducts} static method. 59 | * 60 | * @param driverClass 61 | * @return 62 | */ 63 | @SuppressWarnings("unchecked") 64 | ProbeTable addDriver(Class driverClass) { 65 | final Method method; 66 | try { 67 | method = driverClass.getMethod("getSupportedDevices"); 68 | } catch (SecurityException e) { 69 | throw new RuntimeException(e); 70 | } catch (NoSuchMethodException e) { 71 | throw new RuntimeException(e); 72 | } 73 | final Map devices; 74 | try { 75 | devices = (Map) method.invoke(null); 76 | } catch (IllegalArgumentException e) { 77 | throw new RuntimeException(e); 78 | } catch (IllegalAccessException e) { 79 | throw new RuntimeException(e); 80 | } catch (InvocationTargetException e) { 81 | throw new RuntimeException(e); 82 | } 83 | for (Map.Entry entry : devices.entrySet()) { 84 | final int vendorId = entry.getKey().intValue(); 85 | for (int productId : entry.getValue()) { 86 | addProduct(vendorId, productId, driverClass); 87 | } 88 | } 89 | 90 | return this; 91 | } 92 | 93 | /** 94 | * Returns the driver for the given (vendor, product) pair, or {@code null} 95 | * if no match. 96 | * 97 | * @param vendorId the USB vendor id 98 | * @param productId the USB product id 99 | * @return the driver class matching this pair, or {@code null} 100 | */ 101 | public Class findDriver(int vendorId, int productId) { 102 | final Pair pair = Pair.create(vendorId, productId); 103 | return mProbeTable.get(pair); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/usb_driver/UsbId.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2011-2013 Google Inc. 2 | * Copyright 2013 mike wakerly 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 | * USA. 18 | * 19 | * Project home page: https://github.com/mik3y/usb-serial-for-android 20 | */ 21 | 22 | package com.hd.serialport.usb_driver; 23 | 24 | /** 25 | * Registry of USB vendor/product ID constants. 26 | * 27 | * Culled from various sources; see 28 | * usb.ids for one listing. 29 | * 30 | * @author mike wakerly (opensource@hoho.com) 31 | */ 32 | public final class UsbId { 33 | 34 | public static final int VENDOR_FTDI = 0x0403; 35 | public static final int FTDI_FT232R = 0x6001; 36 | public static final int FTDI_FT231X = 0x6015; 37 | 38 | public static final int VENDOR_ATMEL = 0x03EB; 39 | public static final int ATMEL_LUFA_CDC_DEMO_APP = 0x2044; 40 | 41 | public static final int VENDOR_ARDUINO = 0x2341; 42 | public static final int ARDUINO_UNO = 0x0001; 43 | public static final int ARDUINO_MEGA_2560 = 0x0010; 44 | public static final int ARDUINO_SERIAL_ADAPTER = 0x003b; 45 | public static final int ARDUINO_MEGA_ADK = 0x003f; 46 | public static final int ARDUINO_MEGA_2560_R3 = 0x0042; 47 | public static final int ARDUINO_UNO_R3 = 0x0043; 48 | public static final int ARDUINO_MEGA_ADK_R3 = 0x0044; 49 | public static final int ARDUINO_SERIAL_ADAPTER_R3 = 0x0044; 50 | public static final int ARDUINO_LEONARDO = 0x8036; 51 | public static final int ARDUINO_MICRO = 0x8037; 52 | 53 | public static final int VENDOR_VAN_OOIJEN_TECH = 0x16c0; 54 | public static final int VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL = 0x0483; 55 | public static final int VENDOR_VAN_COM3 = 0x5740; 56 | 57 | public static final int VENDOR_LEAFLABS = 0x1eaf; 58 | public static final int LEAFLABS_MAPLE = 0x0004; 59 | 60 | public static final int VENDOR_SILABS = 0x10c4; 61 | public static final int SILABS_CP2102 = 0xea60; 62 | public static final int SILABS_CP2105 = 0xea70; 63 | public static final int SILABS_CP2108 = 0xea71; 64 | public static final int SILABS_CP2110 = 0xea80; 65 | 66 | public static final int VENDOR_PROLIFIC = 0x067b; 67 | public static final int PROLIFIC_PL2303 = 0x2303; 68 | 69 | public static final int VENDOR_QINHENG = 0x1a86; 70 | public static final int QINHENG_HL340 = 0x7523; 71 | public static final int QINHENG_CH341 = 0x5523; 72 | 73 | private UsbId() { 74 | throw new IllegalAccessError("Non-instantiable class."); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/usb_driver/UsbSerialDriver.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2011-2013 Google Inc. 2 | * Copyright 2013 mike wakerly 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 | * USA. 18 | * 19 | * Project home page: https://github.com/mik3y/usb-serial-for-android 20 | */ 21 | 22 | package com.hd.serialport.usb_driver; 23 | 24 | import android.hardware.usb.UsbDevice; 25 | 26 | import com.hd.serialport.config.UsbPortDeviceType; 27 | 28 | import java.util.List; 29 | 30 | /** 31 | * 32 | * @author mike wakerly (opensource@hoho.com) 33 | */ 34 | public interface UsbSerialDriver { 35 | 36 | /** 37 | * Returns the raw {@link UsbDevice} backing this port. 38 | * 39 | * @return the device 40 | */ 41 | public UsbDevice getDevice(); 42 | 43 | /** 44 | * Returns all available ports for this device. This list must have at least one entry. 45 | * 46 | * @return the ports 47 | */ 48 | public List getPorts(); 49 | 50 | /** 51 | * @return usb port device type {@link UsbPortDeviceType} 52 | */ 53 | public UsbPortDeviceType getDeviceType(); 54 | } 55 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/usb_driver/UsbSerialPort.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2011-2013 Google Inc. 2 | * Copyright 2013 mike wakerly 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 | * USA. 18 | * 19 | * Project home page: https://github.com/mik3y/usb-serial-for-android 20 | */ 21 | 22 | package com.hd.serialport.usb_driver; 23 | 24 | import android.hardware.usb.UsbDeviceConnection; 25 | import android.hardware.usb.UsbManager; 26 | 27 | import java.io.IOException; 28 | 29 | /** 30 | * Interface for a single serial port. 31 | * 32 | * @author mike wakerly (opensource@hoho.com) 33 | */ 34 | public interface UsbSerialPort { 35 | 36 | /** 5 data bits. */ 37 | public static final int DATABITS_5 = 5; 38 | 39 | /** 6 data bits. */ 40 | public static final int DATABITS_6 = 6; 41 | 42 | /** 7 data bits. */ 43 | public static final int DATABITS_7 = 7; 44 | 45 | /** 8 data bits. */ 46 | public static final int DATABITS_8 = 8; 47 | 48 | /** No flow control. */ 49 | public static final int FLOWCONTROL_NONE = 0; 50 | 51 | /** RTS/CTS input flow control. */ 52 | public static final int FLOWCONTROL_RTSCTS_IN = 1; 53 | 54 | /** RTS/CTS output flow control. */ 55 | public static final int FLOWCONTROL_RTSCTS_OUT = 2; 56 | 57 | /** XON/XOFF input flow control. */ 58 | public static final int FLOWCONTROL_XONXOFF_IN = 4; 59 | 60 | /** XON/XOFF output flow control. */ 61 | public static final int FLOWCONTROL_XONXOFF_OUT = 8; 62 | 63 | /** No parity. */ 64 | public static final int PARITY_NONE = 0; 65 | 66 | /** Odd parity. */ 67 | public static final int PARITY_ODD = 1; 68 | 69 | /** Even parity. */ 70 | public static final int PARITY_EVEN = 2; 71 | 72 | /** Mark parity. */ 73 | public static final int PARITY_MARK = 3; 74 | 75 | /** Space parity. */ 76 | public static final int PARITY_SPACE = 4; 77 | 78 | /** 1 stop bit. */ 79 | public static final int STOPBITS_1 = 1; 80 | 81 | /** 1.5 stop bits. */ 82 | public static final int STOPBITS_1_5 = 3; 83 | 84 | /** 2 stop bits. */ 85 | public static final int STOPBITS_2 = 2; 86 | 87 | public UsbSerialDriver getDriver(); 88 | 89 | /** 90 | * Port number within driver. 91 | */ 92 | public int getPortNumber(); 93 | 94 | public UsbDeviceConnection getUsbDeviceConnection(); 95 | 96 | /** 97 | * The serial number of the underlying UsbDeviceConnection, or {@code null}. 98 | */ 99 | public String getSerial(); 100 | 101 | /** 102 | * Opens and initializes the port. Upon success, caller must ensure that 103 | * {@link #close()} is eventually called. 104 | * 105 | * @param connection an open device connection, acquired with 106 | * {@link UsbManager#openDevice(android.hardware.usb.UsbDevice)} 107 | * @throws IOException on error opening or initializing the port. 108 | */ 109 | public void open(UsbDeviceConnection connection) throws IOException; 110 | 111 | /** 112 | * Closes the port. 113 | * 114 | * @throws IOException on error closing the port. 115 | */ 116 | public void close() throws IOException; 117 | 118 | /** 119 | * Reads as many bytes as possible into the destination buffer. 120 | * 121 | * @param dest the destination byte buffer 122 | * @param timeoutMillis the timeout for reading 123 | * @return the actual number of bytes read 124 | * @throws IOException if an error occurred during reading 125 | */ 126 | public int read(final byte[] dest, final int timeoutMillis) throws IOException; 127 | 128 | /** 129 | * Writes as many bytes as possible from the source buffer. 130 | * 131 | * @param src the source byte buffer 132 | * @param timeoutMillis the timeout for writing 133 | * @return the actual number of bytes written 134 | * @throws IOException if an error occurred during writing 135 | */ 136 | public int write(final byte[] src, final int timeoutMillis) throws IOException; 137 | 138 | /** 139 | * Sets various serial port parameters. 140 | * 141 | * @param baudRate baud rate as an integer, for example {@code 115200}. 142 | * @param dataBits one of {@link #DATABITS_5}, {@link #DATABITS_6}, 143 | * {@link #DATABITS_7}, or {@link #DATABITS_8}. 144 | * @param stopBits one of {@link #STOPBITS_1}, {@link #STOPBITS_1_5}, or 145 | * {@link #STOPBITS_2}. 146 | * @param parity one of {@link #PARITY_NONE}, {@link #PARITY_ODD}, 147 | * {@link #PARITY_EVEN}, {@link #PARITY_MARK}, or 148 | * {@link #PARITY_SPACE}. 149 | * @throws IOException on error setting the port parameters 150 | */ 151 | public void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException; 152 | 153 | /** 154 | * Gets the CD (Carrier Detect) bit from the underlying UART. 155 | * 156 | * @return the current state, or {@code false} if not supported. 157 | * @throws IOException if an error occurred during reading 158 | */ 159 | public boolean getCD() throws IOException; 160 | 161 | /** 162 | * Gets the CTS (Clear To Send) bit from the underlying UART. 163 | * 164 | * @return the current state, or {@code false} if not supported. 165 | * @throws IOException if an error occurred during reading 166 | */ 167 | public boolean getCTS() throws IOException; 168 | 169 | /** 170 | * Gets the DSR (Data Set Ready) bit from the underlying UART. 171 | * 172 | * @return the current state, or {@code false} if not supported. 173 | * @throws IOException if an error occurred during reading 174 | */ 175 | public boolean getDSR() throws IOException; 176 | 177 | /** 178 | * Gets the DTR (Data Terminal Ready) bit from the underlying UART. 179 | * 180 | * @return the current state, or {@code false} if not supported. 181 | * @throws IOException if an error occurred during reading 182 | */ 183 | public boolean getDTR() throws IOException; 184 | 185 | /** 186 | * Sets the DTR (Data Terminal Ready) bit on the underlying UART, if 187 | * supported. 188 | * 189 | * @param value the value to set 190 | * @throws IOException if an error occurred during writing 191 | */ 192 | public void setDTR(boolean value) throws IOException; 193 | 194 | /** 195 | * Gets the RI (Ring Indicator) bit from the underlying UART. 196 | * 197 | * @return the current state, or {@code false} if not supported. 198 | * @throws IOException if an error occurred during reading 199 | */ 200 | public boolean getRI() throws IOException; 201 | 202 | /** 203 | * Gets the RTS (Request To Send) bit from the underlying UART. 204 | * 205 | * @return the current state, or {@code false} if not supported. 206 | * @throws IOException if an error occurred during reading 207 | */ 208 | public boolean getRTS() throws IOException; 209 | 210 | /** 211 | * Sets the RTS (Request To Send) bit on the underlying UART, if 212 | * supported. 213 | * 214 | * @param value the value to set 215 | * @throws IOException if an error occurred during writing 216 | */ 217 | public void setRTS(boolean value) throws IOException; 218 | 219 | /** 220 | * Flush non-transmitted output data and / or non-read input data 221 | * @param flushRX {@code true} to flush non-transmitted output data 222 | * @param flushTX {@code true} to flush non-read input data 223 | * @return {@code true} if the operation was successful, or 224 | * {@code false} if the operation is not supported by the driver or device 225 | * @throws IOException if an error occurred during flush 226 | */ 227 | public boolean purgeHwBuffers(boolean flushRX, boolean flushTX) throws IOException; 228 | 229 | } 230 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/usb_driver/UsbSerialProber.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2011-2013 Google Inc. 2 | * Copyright 2013 mike wakerly 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 | * USA. 18 | * 19 | * Project home page: https://github.com/mik3y/usb-serial-for-android 20 | */ 21 | 22 | package com.hd.serialport.usb_driver; 23 | 24 | import android.hardware.usb.UsbDevice; 25 | import android.hardware.usb.UsbManager; 26 | import android.support.annotation.Keep; 27 | import android.text.TextUtils; 28 | import android.util.Pair; 29 | 30 | import com.hd.serialport.config.DriversType; 31 | import com.hd.serialport.usb_driver.extend.UsbExtendDriver; 32 | 33 | import java.lang.reflect.Constructor; 34 | import java.util.ArrayList; 35 | import java.util.Arrays; 36 | import java.util.HashMap; 37 | import java.util.Iterator; 38 | import java.util.List; 39 | import java.util.Map; 40 | 41 | /** 42 | * @author mike wakerly (opensource@hoho.com) 43 | */ 44 | public class UsbSerialProber { 45 | 46 | private final ProbeTable mProbeTable; 47 | 48 | public UsbSerialProber(ProbeTable probeTable) { 49 | mProbeTable = probeTable; 50 | } 51 | 52 | public static UsbSerialProber getDefaultProber() { 53 | return new UsbSerialProber(getDefaultProbeTable()); 54 | } 55 | 56 | private static ProbeTable getDefaultProbeTable() { 57 | final ProbeTable probeTable = new ProbeTable(); 58 | final List>> drivers = new UsbExtendDriver().getExtendDrivers(); 59 | 60 | List defaultTypeList = Arrays.asList(DriversType.USB_CDC_ACM, DriversType.USB_CP21xx,// 61 | DriversType.USB_FTD, DriversType.USB_PL2303,// 62 | DriversType.USB_CH34xx); 63 | 64 | List> defaultDriverList = Arrays.asList(CdcAcmSerialDriver.class, Cp21xxSerialDriver.class,// 65 | FtdiSerialDriver.class, ProlificSerialDriver.class,// 66 | Ch34xSerialDriver.class); 67 | if(null != drivers && !drivers.isEmpty()) { 68 | int index; 69 | for (Pair> pair : drivers) { 70 | index = defaultTypeList.indexOf(pair.first); 71 | if (index > 0) { 72 | defaultDriverList.remove(index); 73 | } 74 | probeTable.addDriver(pair.second); 75 | } 76 | } 77 | for (Class driver : defaultDriverList) { 78 | probeTable.addDriver(driver); 79 | } 80 | return probeTable; 81 | } 82 | 83 | /** 84 | * Finds and builds all possible {@link UsbSerialDriver UsbSerialDrivers} 85 | * from the currently-attached {@link UsbDevice} hierarchy. This method does 86 | * not require permission from the Android USB system, since it does not 87 | * open any of the devices. 88 | * 89 | * @param usbManager 90 | * 91 | * @return a list, possibly empty, of all compatible drivers 92 | */ 93 | @Keep 94 | public List findAllDrivers(final UsbManager usbManager) { 95 | final List result = new ArrayList(); 96 | HashMap deviceList = usbManager.getDeviceList(); 97 | Iterator deviceIterator = deviceList.values().iterator(); 98 | while (deviceIterator.hasNext()) { 99 | UsbDevice usbDevice = deviceIterator.next(); 100 | UsbSerialDriver driver = probeDevice(usbDevice); 101 | if (driver != null) { 102 | result.add(driver); 103 | } 104 | } 105 | return result; 106 | } 107 | 108 | /** 109 | * Probes a single device for a compatible driver. 110 | * 111 | * @param usbDevice the usb device to probe 112 | * 113 | * @return a new {@link UsbSerialDriver} compatible with this device, or 114 | * {@code null} if none available. 115 | */ 116 | @Keep 117 | public UsbSerialDriver probeDevice(final UsbDevice usbDevice) { 118 | final int vendorId = usbDevice.getVendorId(); 119 | final int productId = usbDevice.getProductId(); 120 | final Class driverClass = mProbeTable.findDriver(vendorId, productId); 121 | return getUsbSerialDriver(usbDevice, driverClass); 122 | } 123 | 124 | @Keep 125 | public UsbSerialDriver probeDevice(final UsbDevice usbDevice, String driverName) { 126 | if(TextUtils.isEmpty(driverName))return probeDevice(usbDevice); 127 | UsbSerialDriver driver = null; 128 | Map, Class> table = mProbeTable.getProbeTable(); 129 | for (Map.Entry, Class> entry : table.entrySet()) { 130 | driver = getUsbSerialDriver(usbDevice, entry.getValue()); 131 | if (null != driver && driverName.equals(driver.getDeviceType().getValue())) { 132 | return driver; 133 | } 134 | } 135 | return driver; 136 | } 137 | 138 | private UsbSerialDriver getUsbSerialDriver(UsbDevice usbDevice, Class driverClass) { 139 | if (driverClass != null) { 140 | final UsbSerialDriver driver; 141 | try { 142 | final Constructor constructor = driverClass.getConstructor(UsbDevice.class); 143 | driver = constructor.newInstance(usbDevice); 144 | } catch (Exception e) { 145 | throw new RuntimeException(e); 146 | } 147 | return driver; 148 | } 149 | return null; 150 | } 151 | 152 | public UsbSerialDriver convertDriver(UsbDevice usbDevice, String driverName) { 153 | UsbSerialDriver driver = probeDevice(usbDevice); 154 | if (driver == null) { 155 | driver = probeDevice(usbDevice, driverName); 156 | } 157 | if (driver == null) 158 | throw new NullPointerException("unknown usb device type name : " + driverName); 159 | return driver; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/usb_driver/extend/UsbExtendDriver.java: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.usb_driver.extend; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.util.Pair; 5 | 6 | import com.hd.serialport.usb_driver.UsbSerialDriver; 7 | 8 | import java.lang.reflect.Method; 9 | import java.util.List; 10 | import java.util.function.Consumer; 11 | 12 | /** 13 | * Created by hd on 2019-08-26 . 14 | *

15 | * usb驱动扩展 16 | *

17 | * 1.扩展的serial driver 需要继承 {@link com.hd.serialport.usb_driver.CommonUsbSerialDriver} 18 | * 2.扩展的serial port 需要继承 {@link com.hd.serialport.usb_driver.CommonUsbSerialPort} 19 | * 3.扩展的serial driver类方法 getDeviceType,理论上需要写成 : 20 | * ``` 21 | * @Override public String setDriverName() { 22 | * return "custom value"; 23 | * } 24 | * ``` 25 | * 4.扩展的serial port 类需要添加`getSupportedDevices`方法 ,如下: 26 | * ``` 27 | * public static Map getSupportedDevices() { 28 | * final Map supportedDevices = new LinkedHashMap(); 29 | * supportedDevices.put(UsbId.VENDOR_QINHENG, new int[]{UsbId.QINHENG_HL340, UsbId.QINHENG_CH341}); 30 | * return supportedDevices; 31 | * } 32 | * ``` 33 | */ 34 | @SuppressWarnings("ALL") 35 | public class UsbExtendDriver { 36 | 37 | private static List>> extendDrivers; 38 | 39 | public UsbExtendDriver() { } 40 | 41 | private UsbExtendDriver(Extender extender) { 42 | extendDrivers = extender.drivers; 43 | } 44 | 45 | private void clearExtendDrivers(){ 46 | extendDrivers.clear(); 47 | extendDrivers = null; 48 | } 49 | 50 | public List>> getExtendDrivers(){ 51 | return extendDrivers; 52 | } 53 | 54 | public static class Extender { 55 | 56 | public Extender Extender() { return new Extender();} 57 | 58 | private List>> drivers; 59 | 60 | /** 61 | * e.g. 62 | * List list = new ArrayList(); 63 | * list.add(new Pair("custom1 value",CustomDriver1.class)); 64 | * list.add(new Pair("custom2 value",CustomDriver2.class)); 65 | * list.add(new Pair("custom3 value",CustomDriver3.class)); 66 | * setDrivers(list); 67 | */ 68 | public Extender setDrivers(@NonNull List>> drivers) { 69 | this.drivers = drivers; 70 | return this; 71 | } 72 | 73 | public void clearExtendDrivers(){ 74 | new UsbExtendDriver().clearExtendDrivers(); 75 | } 76 | 77 | public void extend() { 78 | drivers.forEach(new Consumer>>() { 79 | @Override 80 | public void accept(Pair> driver) { 81 | if (driver.first.isEmpty()) throw new NullPointerException("custom extended usb driver name must be not null !!"); 82 | try { 83 | Method method = driver.second.getMethod("getSupportedDevices"); 84 | } catch (Exception e) { 85 | throw new RuntimeException("custom extended usb driver must add a method named 'getSupportedDevices' !"); 86 | } 87 | } 88 | }); 89 | new UsbExtendDriver(this); 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/utils/HexDump.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.hd.serialport.utils; 18 | 19 | import java.util.Arrays; 20 | 21 | /** 22 | * Clone of Android's HexDump class, for use in debugging. Cosmetic changes only. 23 | */ 24 | public class HexDump { 25 | private final static char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 26 | private final static String[] binaryArray = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"}; 27 | private final static String hexStr= Arrays.toString(HEX_DIGITS); 28 | public static String dumpHexString(byte[] array) { 29 | return dumpHexString(array, 0, array.length); 30 | } 31 | 32 | public static String dumpHexString(byte[] array, int offset, int length) { 33 | StringBuilder result = new StringBuilder(); 34 | byte[] line = new byte[16]; 35 | int lineIndex = 0; 36 | result.append("\n0x"); 37 | result.append(toHexString(offset)); 38 | 39 | for (int i = offset; i < offset + length; i++) { 40 | if (lineIndex == 16) { 41 | result.append(" "); 42 | 43 | for (int j = 0; j < 16; j++) { 44 | if (line[j] > ' ' && line[j] < '~') { 45 | result.append(new String(line, j, 1)); 46 | } else { 47 | result.append("."); 48 | } 49 | } 50 | 51 | result.append("\n0x"); 52 | result.append(toHexString(i)); 53 | lineIndex = 0; 54 | } 55 | 56 | byte b = array[i]; 57 | result.append(" "); 58 | result.append(HEX_DIGITS[(b >>> 4) & 0x0F]); 59 | result.append(HEX_DIGITS[b & 0x0F]); 60 | 61 | line[lineIndex++] = b; 62 | } 63 | 64 | if (lineIndex != 16) { 65 | int count = (16 - lineIndex) * 3; 66 | count++; 67 | for (int i = 0; i < count; i++) { 68 | result.append(" "); 69 | } 70 | 71 | for (int i = 0; i < lineIndex; i++) { 72 | if (line[i] > ' ' && line[i] < '~') { 73 | result.append(new String(line, i, 1)); 74 | } else { 75 | result.append("."); 76 | } 77 | } 78 | } 79 | 80 | return result.toString(); 81 | } 82 | 83 | public static String hextoString(byte[] array) { 84 | return hextoString(array, 0, array.length); 85 | } 86 | 87 | public static String hextoString(byte[] array, int offset, int length) { 88 | StringBuilder result = new StringBuilder(); 89 | for (int i = offset; i < offset + length; i++) { 90 | result.append(HEX_DIGITS[array[i] & 0x0F]); 91 | } 92 | return result.toString(); 93 | } 94 | 95 | /** 96 | * 字节数组转为普通字符串(ASCII对应的字符) 97 | * 98 | * @param bytearray byte[] 99 | * 100 | * @return String 101 | */ 102 | public static String bytetoString(byte[] bytearray) { 103 | String result = ""; 104 | char temp; 105 | 106 | int length = bytearray.length; 107 | for (byte aBytearray : bytearray) { 108 | temp = (char) aBytearray; 109 | result += temp; 110 | } 111 | return result; 112 | } 113 | 114 | public static String toHexString(byte b) { 115 | return toHexString(toByteArray(b)); 116 | } 117 | 118 | public static String toHexString(byte[] array) { 119 | return toHexString(array, 0, array.length); 120 | } 121 | 122 | public static String toHexString(byte[] array, int offset, int length) { 123 | char[] buf = new char[length * 2]; 124 | 125 | int bufIndex = 0; 126 | for (int i = offset; i < offset + length; i++) { 127 | byte b = array[i]; 128 | buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F]; 129 | buf[bufIndex++] = HEX_DIGITS[b & 0x0F]; 130 | } 131 | 132 | return new String(buf); 133 | } 134 | 135 | public static String toHexString(int i) { 136 | return toHexString(toByteArray(i)); 137 | } 138 | 139 | public static String toHexString(short i) { 140 | return toHexString(toByteArray(i)); 141 | } 142 | 143 | public static byte[] toByteArray(byte b) { 144 | byte[] array = new byte[1]; 145 | array[0] = b; 146 | return array; 147 | } 148 | 149 | public static byte[] toByteArray(int i) { 150 | byte[] array = new byte[4]; 151 | array[3] = (byte) (i & 0xFF); 152 | array[2] = (byte) ((i >> 8) & 0xFF); 153 | array[1] = (byte) ((i >> 16) & 0xFF); 154 | array[0] = (byte) ((i >> 24) & 0xFF); 155 | 156 | return array; 157 | } 158 | 159 | public static byte[] toByteArray(short i) { 160 | byte[] array = new byte[2]; 161 | array[1] = (byte) (i & 0xFF); 162 | array[0] = (byte) ((i >> 8) & 0xFF); 163 | 164 | return array; 165 | } 166 | 167 | private static int toByte(char c) { 168 | if (c >= '0' && c <= '9') 169 | return (c - '0'); 170 | if (c >= 'A' && c <= 'F') 171 | return (c - 'A' + 10); 172 | if (c >= 'a' && c <= 'f') 173 | return (c - 'a' + 10); 174 | 175 | throw new RuntimeException("Invalid hex char '" + c + "'"); 176 | } 177 | 178 | public static byte[] hexStringToByteArray(String hexString) { 179 | int length = hexString.length(); 180 | byte[] buffer = new byte[length / 2]; 181 | for (int i = 0; i < length; i += 2) { 182 | buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1))); 183 | } 184 | return buffer; 185 | } 186 | 187 | /** 188 | * @param hexString 189 | * 190 | * @return 将十六进制转换为二进制字符串 16-2 191 | */ 192 | public static String hexStrBinaryStr(String hexString) { 193 | return bytes2BinStr(hexStrToBinary(hexString)); 194 | } 195 | 196 | /** 197 | * @param hexString 198 | * 199 | * @return 将十六进制转换为二进制字节数组 16-2 200 | */ 201 | public static byte[] hexStrToBinary(String hexString){ 202 | //hexString的长度对2取整,作为bytes的长度 203 | int len = hexString.length() / 2; 204 | byte[] bytes = new byte[len]; 205 | byte high = 0;//字节高四位 206 | byte low = 0;//字节低四位 207 | for (int i = 0; i < len; i++) { 208 | //右移四位得到高位 209 | high = (byte)((hexStr.indexOf(hexString.charAt(2*i)))<<4); 210 | low = (byte)hexStr.indexOf(hexString.charAt(2*i+1)); 211 | bytes[i] = (byte) (high | low);//高地位做或运算 212 | } 213 | return bytes; 214 | } 215 | 216 | 217 | /** 218 | * @return 二进制数组转换为二进制字符串 2-2 219 | */ 220 | public static String bytes2BinStr(byte[] bArray) { 221 | String outStr = ""; 222 | int pos = 0; 223 | for (byte b : bArray) { 224 | //高四位 225 | pos = (b & 0xF0) >> 4; 226 | outStr += binaryArray[pos]; 227 | //低四位 228 | pos = b & 0x0F; 229 | outStr += binaryArray[pos]; 230 | } 231 | return outStr; 232 | } 233 | 234 | /** 235 | * 将传入的十六进制字符串按位两两异或 最终得到异或校验和 236 | * 237 | * @param hexStr 238 | * @return 239 | */ 240 | public static String checkSum(String hexStr) { 241 | if (hexStr.length() < 2) { 242 | // 保证必须有one byte十六进制字符 243 | return null; 244 | } 245 | String x = null; 246 | for (int i = 0; i < hexStr.length() / 2 - 1; i++) { 247 | if (i == 0) { 248 | x = hexStr.substring(i, i + 2); 249 | } 250 | String y = hexStr.substring(i * 2 + 2, i * 2 + 4); 251 | x = xor(x, y); 252 | } 253 | return x; 254 | } 255 | 256 | /** 257 | * 将传入的两个one byte十六进制字符异或 258 | * 259 | * @param strHex_X 260 | * @param strHex_Y 261 | * @return 262 | */ 263 | private static String xor(String strHex_X, String strHex_Y) { 264 | // 将x、y转成二进制形式 265 | String anotherBinary = Integer.toBinaryString(Integer.valueOf(strHex_X, 266 | 16)); 267 | String thisBinary = Integer.toBinaryString(Integer 268 | .valueOf(strHex_Y, 16)); 269 | String result = ""; 270 | // 判断是否为8位二进制,否则左补零 271 | if (anotherBinary.length() != 8) { 272 | for (int i = anotherBinary.length(); i < 8; i++) { 273 | anotherBinary = "0" + anotherBinary; 274 | } 275 | } 276 | if (thisBinary.length() != 8) { 277 | for (int i = thisBinary.length(); i < 8; i++) { 278 | thisBinary = "0" + thisBinary; 279 | } 280 | } 281 | // 异或运算 282 | for (int i = 0; i < anotherBinary.length(); i++) { 283 | // 如果相同位置数相同,则补0,否则补1 284 | if (thisBinary.charAt(i) == anotherBinary.charAt(i)) 285 | result += "0"; 286 | else { 287 | result += "1"; 288 | } 289 | } 290 | return Integer.toHexString(Integer.parseInt(result, 2)); 291 | } 292 | 293 | /** 294 | * 字符串的16进制累加和 295 | */ 296 | public static String makeChecksum(String data) { 297 | if (data == null || data.equals("")) { 298 | return ""; 299 | } 300 | int total = 0; 301 | int len = data.length(); 302 | int num = 0; 303 | while (num < len) { 304 | String s = data.substring(num, num + 2); 305 | System.out.println(s); 306 | total += Integer.parseInt(s, 16); 307 | num = num + 2; 308 | } 309 | //用256求余最大是255,即16进制的FF 310 | int mod = total % 256; 311 | String hex = Integer.toHexString(mod); 312 | len = hex.length(); 313 | // 如果不够校验位的长度,补0,这里用的是两位校验 314 | if (len < 2) { 315 | hex = "0" + hex; 316 | } 317 | return hex; 318 | } 319 | } 320 | -------------------------------------------------------------------------------- /usbserialport/src/main/java/com/hd/serialport/utils/L.kt: -------------------------------------------------------------------------------- 1 | package com.hd.serialport.utils 2 | 3 | import android.util.Log 4 | import com.hd.serialport.BuildConfig 5 | 6 | /** 7 | * Created by hd on 2017/5/8. 8 | * 9 | */ 10 | object L { 11 | var allowLog = BuildConfig.DEBUG 12 | private val TAG = "usb-serial-port" 13 | fun i(i: String) { 14 | i(TAG, i) 15 | } 16 | 17 | fun d(d: String) { 18 | d(TAG, d) 19 | } 20 | 21 | fun w(w: String) { 22 | w(TAG, w) 23 | } 24 | 25 | fun e(e: String) { 26 | e(TAG, e) 27 | } 28 | 29 | fun i(tag: String?, i: String) { 30 | if (allowLog) 31 | Log.i(tag ?: TAG, i) 32 | } 33 | 34 | fun d(tag: String?, d: String) { 35 | if (allowLog) 36 | Log.d(tag ?: TAG, d) 37 | } 38 | 39 | fun w(tag: String?, w: String) { 40 | if (allowLog) 41 | Log.w(tag ?: TAG, w) 42 | } 43 | 44 | fun e(tag: String?, e: String) { 45 | if (allowLog) 46 | Log.e(tag ?: TAG, e) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /usbserialport/src/main/jniLibs/arm64-v8a/libserial_port.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/main/jniLibs/arm64-v8a/libserial_port.so -------------------------------------------------------------------------------- /usbserialport/src/main/jniLibs/armeabi-v7a/libserial_port.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/main/jniLibs/armeabi-v7a/libserial_port.so -------------------------------------------------------------------------------- /usbserialport/src/main/jniLibs/armeabi/libserial_port.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/main/jniLibs/armeabi/libserial_port.so -------------------------------------------------------------------------------- /usbserialport/src/main/jniLibs/mips/libserial_port.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/main/jniLibs/mips/libserial_port.so -------------------------------------------------------------------------------- /usbserialport/src/main/jniLibs/mips64/libserial_port.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/main/jniLibs/mips64/libserial_port.so -------------------------------------------------------------------------------- /usbserialport/src/main/jniLibs/x86/libserial_port.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/main/jniLibs/x86/libserial_port.so -------------------------------------------------------------------------------- /usbserialport/src/main/jniLibs/x86_64/libserial_port.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloHuDi/usb-with-serial-port/68f3fef3782f1c98681080ee062f04f8f6d5bf7a/usbserialport/src/main/jniLibs/x86_64/libserial_port.so -------------------------------------------------------------------------------- /usbserialport/src/main/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | usbSerialPort 3 | 检测到当前系统存在usb模块Bug,请与厂商联系 4 | 查找设备失败 5 | 打开设备失败 6 | 本次测量失败 7 | 权限请求失败 8 | 参数错误,串口打开失败 9 | 当前串口没有读写权限 10 | 串口打开失败 11 | 12 | -------------------------------------------------------------------------------- /usbserialport/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | usbSerialPort 3 | USB module Bug is detected in the current system, please contact the vendor 4 | Lookup device failure 5 | Open device failure 6 | Failure of this measurement 7 | Permission request failure 8 | Error of parameter, failure to open serial port 9 | No read and write permissions in the current serial port 10 | Failure to open serial port 11 | 12 | --------------------------------------------------------------------------------