Skip to content

Commit

Permalink
Merge pull request #380 from magnusja/feature/avoid-segfault
Browse files Browse the repository at this point in the history
Prevent communication usage after closing
  • Loading branch information
magnusja authored Mar 11, 2023
2 parents 428d618 + 00bb5aa commit 41ebafd
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal abstract class AndroidUsbCommunication(

private var isNativeInited: Boolean = false
var deviceConnection: UsbDeviceConnection? = null
private var isClosed = false
protected var isClosed = false

init {
initNativeLibrary()
Expand Down Expand Up @@ -49,10 +49,14 @@ internal abstract class AndroidUsbCommunication(
}

override fun controlTransfer(requestType: Int, request: Int, value: Int, index: Int, buffer: ByteArray, length: Int): Int {
require(!isClosed) { "device is closed" }

return deviceConnection!!.controlTransfer(requestType, request, value, index, buffer, length, TRANSFER_TIMEOUT)
}

override fun resetDevice() {
require(!isClosed) { "device is closed" }

Log.d(TAG, "Performing native reset")

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

override fun clearFeatureHalt(endpoint: UsbEndpoint) {
require(!isClosed) { "device is closed" }

Log.w(TAG, "Clearing halt on endpoint $endpoint (direction ${endpoint.direction})")
val result = clearHaltNative(deviceConnection!!.fileDescriptor, endpoint.address)
if (!result) {
Expand All @@ -90,6 +96,8 @@ internal abstract class AndroidUsbCommunication(
}

override fun close() {
require(!isClosed) { "device is already closed" }

Log.d(TAG, "close device")
closeUsbConnection()
isClosed = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ internal class HoneyCombMr1Communication(

@Throws(IOException::class)
override fun bulkOutTransfer(src: ByteBuffer): Int {
require(!isClosed) { "device is closed" }

val offset = src.position()

if (offset == 0) {
Expand Down Expand Up @@ -54,6 +56,8 @@ internal class HoneyCombMr1Communication(

@Throws(IOException::class)
override fun bulkInTransfer(dest: ByteBuffer): Int {
require(!isClosed) { "device is closed" }

val offset = dest.position()

if (offset == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ internal class JellyBeanMr2Communication(

@Throws(IOException::class)
override fun bulkOutTransfer(src: ByteBuffer): Int {
require(!isClosed) { "device is closed" }

val result = deviceConnection!!.bulkTransfer(outEndpoint,
src.array(), src.position(), src.remaining(), UsbCommunication.TRANSFER_TIMEOUT)

Expand All @@ -46,6 +48,8 @@ internal class JellyBeanMr2Communication(

@Throws(IOException::class)
override fun bulkInTransfer(dest: ByteBuffer): Int {
require(!isClosed) { "device is closed" }

val result = deviceConnection!!.bulkTransfer(inEndpoint,
dest.array(), dest.position(), dest.remaining(), UsbCommunication.TRANSFER_TIMEOUT)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class LibusbCommunication(
private val libUsbHandle: Long
get() = libUsbHandleArray[0]
private var deviceConnection: UsbDeviceConnection?
private var closed = false

init {
System.loadLibrary("libusbcom")
Expand Down Expand Up @@ -59,6 +60,8 @@ class LibusbCommunication(
private external fun nativeControlTransfer(handle: Long, requestType: Int, request: Int, value: Int, index: Int, buffer: ByteArray, length: Int, timeout: Int): Int

override fun bulkOutTransfer(src: ByteBuffer): Int {
require(!closed) { "device is closed" }

val transferred = nativeBulkTransfer(
libUsbHandle, outEndpoint.address, src.array(), src.position(), src.remaining(),
TRANSFER_TIMEOUT
Expand All @@ -74,6 +77,8 @@ class LibusbCommunication(
}

override fun bulkInTransfer(dest: ByteBuffer): Int {
require(!closed) { "device is closed" }

val transferred = nativeBulkTransfer(
libUsbHandle, inEndpoint.address, dest.array(), dest.position(), dest.remaining(),
TRANSFER_TIMEOUT
Expand All @@ -89,6 +94,8 @@ class LibusbCommunication(
}

override fun controlTransfer(requestType: Int, request: Int, value: Int, index: Int, buffer: ByteArray, length: Int): Int {
require(!closed) { "device is closed" }

val ret = nativeControlTransfer(libUsbHandle, requestType, request, value, index, buffer, length, TRANSFER_TIMEOUT)
if (ret < 0) {
throw LibusbException("libusb control transfer failed", LibusbError.fromCode(ret))
Expand All @@ -97,6 +104,8 @@ class LibusbCommunication(
}

override fun resetDevice() {
require(!closed) { "device is closed" }

if (!deviceConnection!!.releaseInterface(usbInterface)) {
Log.w(TAG, "Failed to release interface, errno: ${ErrNo.errno} ${ErrNo.errstr}")
}
Expand All @@ -118,14 +127,22 @@ class LibusbCommunication(
}

override fun clearFeatureHalt(endpoint: UsbEndpoint) {
require(!closed) { "device is closed" }

val ret = nativeClearHalt(libUsbHandle, endpoint.address)
Log.d(TAG, "libusb clearFeatureHalt returned $ret: ${LibusbError.fromCode(ret).message}")
}

override fun close() {
deviceConnection!!.releaseInterface(usbInterface)
nativeClose(libUsbHandle, usbInterface.id)
deviceConnection!!.close()
require(!closed) { "device is already closed" }

try {
deviceConnection!!.releaseInterface(usbInterface)
nativeClose(libUsbHandle, usbInterface.id)
deviceConnection!!.close()
} finally {
closed = true
}
}

companion object {
Expand Down

0 comments on commit 41ebafd

Please sign in to comment.