Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/libusb #242

Merged
merged 15 commits into from
Jan 12, 2020
4 changes: 4 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@ jobs:
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: install libusb
run: wget https://github.com/libusb/libusb/archive/v1.0.23.zip && unzip v1.0.23.zip
- name: write local properties
run: echo "libusb.dir=$GITHUB_WORKSPACE/libusb-1.0.23" > $GITHUB_WORKSPACE/local.properties
- name: Build with Gradle
run: ./gradlew build
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.cxx/

# Created by https://www.gitignore.io/api/android,java,intellij,gradle,maven,eclipse

### Android ###
Expand Down
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ env:
# install timeout in minutes (2 minutes by default)
- ADB_INSTALL_TIMEOUT=8

before_script:
- ls
- wget https://github.com/libusb/libusb/archive/v1.0.23.zip
- unzip v1.0.23.zip
- echo "libusb.dir=$TRAVIS_BUILD_DIR/libusb-1.0.23" > $TRAVIS_BUILD_DIR/local.properties

script:
- ./gradlew build -x bintray jacocoTestReport --stacktrace

Expand Down
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ dependencies {
api project(':httpserver')
api project(':storageprovider')
api project(':javafs')
api project(':libusbcommunication')
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@
import com.github.mjdev.libaums.fs.UsbFileStreamFactory;
import com.github.mjdev.libaums.server.http.UsbFileHttpServerService;
import com.github.mjdev.libaums.server.http.server.AsyncHttpServer;
import com.github.mjdev.libaums.usb.UsbCommunicationFactory;

import me.jahnen.libaums.libusbcommunication.LibusbCommunicationCreator;

/**
* MainActivity of the demo application which shows the contents of the first
Expand All @@ -99,7 +102,9 @@
public class MainActivity extends AppCompatActivity implements OnItemClickListener {

static {
FileSystemFactory.INSTANCE.registerFileSystem(new JavaFsFileSystemCreator());
FileSystemFactory.registerFileSystem(new JavaFsFileSystemCreator());
UsbCommunicationFactory.registerCommunication(new LibusbCommunicationCreator());
UsbCommunicationFactory.setUnderlyingUsbCommunication(UsbCommunicationFactory.UnderlyingUsbCommunication.OTHER);
}

/**
Expand Down
3 changes: 0 additions & 3 deletions bintray.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ artifacts {

// Bintray
File file = project.rootProject.file('local.properties')
if(!file.exists()) {
return
}
Properties properties = new Properties()
properties.load(file.newDataInputStream())

Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.3.41'
ext.kotlin_version = '1.3.61'
repositories {
jcenter()
maven {
Expand All @@ -14,7 +14,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
classpath 'com.android.tools.build:gradle:3.5.3'

classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
Expand Down Expand Up @@ -65,4 +65,4 @@ allprojects {

task clean(type: Delete) {
delete rootProject.buildDir
}
}
2 changes: 1 addition & 1 deletion libaums/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ android {
buildToolsVersion '28.0.3'

defaultConfig {
minSdkVersion 16
minSdkVersion 15
targetSdkVersion 29
versionCode 74
versionName "0.7.4"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.github.mjdev.libaums.ErrNo
import com.github.mjdev.libaums.driver.BlockDeviceDriver
import com.github.mjdev.libaums.driver.scsi.commands.*
import com.github.mjdev.libaums.driver.scsi.commands.CommandBlockWrapper.Direction
import com.github.mjdev.libaums.usb.AndroidUsbCommunication
import com.github.mjdev.libaums.usb.UsbCommunication
import java.io.IOException
import java.nio.ByteBuffer
Expand Down Expand Up @@ -152,14 +153,14 @@ class ScsiBlockDevice(private val usbCommunication: UsbCommunication, private va
}
i % 2 == 0 -> {
Log.d(TAG, "Reset bulk-only mass storage")
usbCommunication.bulkOnlyMassStorageReset()
bulkOnlyMassStorageReset()
Log.d(TAG, "Trying to clear halt on both endpoints")
usbCommunication.clearFeatureHalt(usbCommunication.inEndpoint)
usbCommunication.clearFeatureHalt(usbCommunication.outEndpoint)
}
i % 2 == 1 -> {
Log.d(TAG, "Trying to reset the device")
usbCommunication.resetRecovery()
usbCommunication.resetDevice()
}
}

Expand All @@ -170,6 +171,16 @@ class ScsiBlockDevice(private val usbCommunication: UsbCommunication, private va
throw IllegalStateException("This should never happen.")
}

private fun bulkOnlyMassStorageReset() {
Log.w(TAG, "sending bulk only mass storage request")
val bArr = ByteArray(2)
// REQUEST_BULK_ONLY_MASS_STORAGE_RESET = 255
// REQUEST_TYPE_BULK_ONLY_MASS_STORAGE_RESET = 33
val transferred: Int = usbCommunication.controlTransfer(33, 255, 0, usbCommunication.usbInterface.id, bArr, 0)
if (transferred == -1) {
throw IOException("bulk only mass storage reset failed!")
}
}

@Throws(IOException::class)
private fun transferOneCommand(command: CommandBlockWrapper, inBuffer: ByteBuffer): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ object FileSystemFactory {
* instance.
*/
@Synchronized
@JvmStatic
fun registerFileSystem(creator: FileSystemCreator) {
fileSystems.add(creator)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import java.io.IOException
internal abstract class AndroidUsbCommunication(
private val usbManager: UsbManager,
private val usbDevice: UsbDevice,
private val usbInterface: UsbInterface,
override val usbInterface: UsbInterface,
override val outEndpoint: UsbEndpoint,
override val inEndpoint: UsbEndpoint
) : UsbCommunication {
Expand Down Expand Up @@ -52,12 +52,7 @@ internal abstract class AndroidUsbCommunication(
return deviceConnection!!.controlTransfer(requestType, request, value, index, buffer, length, TRANSFER_TIMEOUT)
}

override fun resetRecovery() = when {
isNativeInited -> nativeReset()
else -> softReset()
}

private fun nativeReset() {
override fun resetDevice() {
Log.d(TAG, "Performing native reset")

if (!deviceConnection!!.releaseInterface(usbInterface)) {
Expand All @@ -74,26 +69,6 @@ internal abstract class AndroidUsbCommunication(
}
}

private fun softReset() {
bulkOnlyMassStorageReset()
Thread.sleep(2000)
clearFeatureHalt(inEndpoint)
Thread.sleep(2000)
clearFeatureHalt(outEndpoint)
Thread.sleep(2000)
}

override fun bulkOnlyMassStorageReset() {
Log.w(TAG, "sending bulk only mass storage request")
val bArr = ByteArray(2)
// REQUEST_BULK_ONLY_MASS_STORAGE_RESET = 255
// REQUEST_TYPE_BULK_ONLY_MASS_STORAGE_RESET = 33
val transferred: Int = controlTransfer(33, 255, 0, usbInterface.id, bArr, 0)
if (transferred == -1) {
throw IOException("bulk only mass storage reset failed!")
}
}

override fun clearFeatureHalt(endpoint: UsbEndpoint) {
Log.w(TAG, "Clearing halt on endpoint $endpoint (direction ${endpoint.direction})")
val result = clearHaltNative(deviceConnection!!.fileDescriptor, endpoint.address)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.github.mjdev.libaums.usb

import android.hardware.usb.UsbEndpoint
import android.hardware.usb.UsbInterface
import java.io.Closeable
import java.io.IOException
import java.nio.ByteBuffer
Expand All @@ -33,6 +34,7 @@ import java.nio.ByteBuffer
interface UsbCommunication : Closeable {
val inEndpoint: UsbEndpoint
val outEndpoint: UsbEndpoint
val usbInterface: UsbInterface

/**
* Performs a bulk out transfer beginning at the offset specified in the
Expand Down Expand Up @@ -73,13 +75,7 @@ interface UsbCommunication : Closeable {
* Performs the recovery reset procedure in case the communication is stalled
*/
@Throws(IOException::class)
fun resetRecovery()

/**
* Attempts a bulk-only mass storage reset control transfer operation
*/
@Throws(IOException::class)
fun bulkOnlyMassStorageReset()
fun resetDevice()

/**
* Attempts to clear the HALT feature from the specified USB endpoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,35 @@ import android.hardware.usb.UsbInterface
import android.hardware.usb.UsbManager
import android.os.Build
import android.util.Log
import com.github.mjdev.libaums.fs.FileSystemCreator
import com.github.mjdev.libaums.fs.FileSystemFactory
import java.io.IOException
import java.util.ArrayList

/**
* Created by magnusja on 21/12/16.
*/

object UsbCommunicationFactory {
class NoUsbCommunicationFound : IOException()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


private val TAG = UsbCommunicationFactory::class.java.simpleName

private val communications = ArrayList<UsbCommunicationCreator>()

@JvmStatic
var underlyingUsbCommunication = UnderlyingUsbCommunication.DEVICE_CONNECTION_SYNC

enum class UnderlyingUsbCommunication {
USB_REQUEST_ASYNC,
DEVICE_CONNECTION_SYNC
DEVICE_CONNECTION_SYNC,
OTHER
}

@Synchronized
@JvmStatic
fun registerCommunication(creator: UsbCommunicationCreator) {
communications.add(creator)
}

fun createUsbCommunication(
Expand All @@ -30,15 +44,36 @@ object UsbCommunicationFactory {
outEndpoint: UsbEndpoint,
inEndpoint: UsbEndpoint
): UsbCommunication {
return if (underlyingUsbCommunication == UnderlyingUsbCommunication.DEVICE_CONNECTION_SYNC) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
JellyBeanMr2Communication(usbManager, usbDevice, usbInterface, outEndpoint, inEndpoint)
} else {
Log.i(TAG, "using workaround usb communication")
HoneyCombMr1Communication(usbManager, usbDevice, usbInterface, outEndpoint, inEndpoint)
}
} else {
UsbRequestCommunication(usbManager, usbDevice, usbInterface, outEndpoint, inEndpoint)
when(underlyingUsbCommunication) {
UnderlyingUsbCommunication.DEVICE_CONNECTION_SYNC ->
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
JellyBeanMr2Communication(usbManager, usbDevice, usbInterface, outEndpoint, inEndpoint)
} else {
Log.i(TAG, "using workaround usb communication")
HoneyCombMr1Communication(usbManager, usbDevice, usbInterface, outEndpoint, inEndpoint)
}

UnderlyingUsbCommunication.USB_REQUEST_ASYNC ->
return UsbRequestCommunication(usbManager, usbDevice, usbInterface, outEndpoint, inEndpoint)

UnderlyingUsbCommunication.OTHER ->
for(creator in communications) {
val communication = creator.create(usbManager, usbDevice, usbInterface, outEndpoint, inEndpoint)

if(communication != null) {
return communication
}
}

}
throw NoUsbCommunicationFound()
}
}

interface UsbCommunicationCreator {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fun create(usbManager: UsbManager,
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usbDevice: UsbDevice,
usbInterface: UsbInterface,
outEndpoint: UsbEndpoint,
inEndpoint: UsbEndpoint): UsbCommunication?
}
2 changes: 2 additions & 0 deletions libusbcommunication/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.cxx/
/build
29 changes: 29 additions & 0 deletions libusbcommunication/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.4.1)

message("Using libusb path ${LIBUSB_PATH}")

set(LIBUSB_SRC "${LIBUSB_PATH}/libusb")
set(LIBUSB_INCLUDE "${LIBUSB_PATH}")


include_directories(${LIBUSB_INCLUDE}/android/) # config.h
include_directories(${LIBUSB_SRC})
add_library( libusb
SHARED
${LIBUSB_SRC}/core.c
${LIBUSB_SRC}/descriptor.c
${LIBUSB_SRC}/hotplug.c
${LIBUSB_SRC}/io.c
${LIBUSB_SRC}/sync.c
${LIBUSB_SRC}/os/linux_usbfs.c
${LIBUSB_SRC}/os/poll_posix.c
${LIBUSB_SRC}/os/threads_posix.c
${LIBUSB_SRC}/os/linux_netlink.c)
target_link_libraries(libusb log)


include_directories(${LIBUSB_INCLUDE})
add_library( libusbcom
SHARED
src/c/usb.c )
target_link_libraries(libusbcom libusb log)
Loading