Skip to content

Commit af89120

Browse files
authoredMar 11, 2023
Merge pull request #381 from magnusja/develop
core v0.10.0 libusbcommunication v0.4.0
2 parents 37d2ed3 + e5a31e9 commit af89120

File tree

15 files changed

+135
-15
lines changed

15 files changed

+135
-15
lines changed
 

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ A library to access USB mass storage devices (pen drives, external HDDs, card re
1313
The library can be included into your project like this:
1414

1515
```ruby
16-
implementation 'me.jahnen.libaums:core:0.9.4'
16+
implementation 'me.jahnen.libaums:core:0.10.0'
1717
```
1818

1919
If you need the HTTP or the storage provider module:

‎libaums/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jacoco {
99

1010
ext {
1111
PUBLISH_GROUP_ID = 'me.jahnen.libaums'
12-
PUBLISH_VERSION = '0.9.4'
12+
PUBLISH_VERSION = '0.10.0'
1313
PUBLISH_ARTIFACT_ID = 'core'
1414
}
1515

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.github.mjdev.libaums.partition.gpt
2+
3+
import android.util.Log
4+
import me.jahnen.libaums.core.driver.BlockDeviceDriver
5+
import me.jahnen.libaums.core.partition.PartitionTable
6+
import me.jahnen.libaums.core.partition.PartitionTableEntry
7+
import java.io.IOException
8+
import java.nio.ByteBuffer
9+
import java.nio.ByteOrder
10+
import java.util.ArrayList
11+
12+
class GPT private constructor(): PartitionTable {
13+
14+
// See also https://en.wikipedia.org/wiki/GUID_Partition_Table
15+
16+
private val partitions = ArrayList<PartitionTableEntry>()
17+
18+
override val size: Int get() = partitions.size * 128
19+
override val partitionTableEntries: List<PartitionTableEntry>
20+
get() = partitions
21+
22+
companion object {
23+
private val TAG = GPT::class.java.simpleName
24+
const val EFI_PART = "EFI PART"
25+
26+
const val GPT_OFFSET = 512 // GPT has a protective MBR, GPT starts after
27+
28+
const val ENTRY_SIZE = 128
29+
30+
const val FIRST_LBA_OFFSET = 32
31+
const val LAST_LBA_OFFSET = 40
32+
33+
@Throws(IOException::class)
34+
fun read(blockDevice: BlockDeviceDriver): GPT? {
35+
val result = GPT()
36+
var buffer = ByteBuffer.allocate(512 * 2)
37+
blockDevice.read(0, buffer)
38+
39+
val efiTestString = String(buffer.array(), GPT_OFFSET, 8, Charsets.US_ASCII)
40+
Log.d(TAG, "EFI test string $efiTestString")
41+
42+
if (efiTestString != EFI_PART) {
43+
return null
44+
}
45+
Log.d(TAG, "EFI test string matches!")
46+
47+
48+
buffer = ByteBuffer.allocate(512 * 34) // at LBA 34 GPT should stop
49+
blockDevice.read(0, buffer)
50+
buffer.order(ByteOrder.LITTLE_ENDIAN)
51+
52+
var entry_offset = 1024
53+
54+
while (buffer[entry_offset].toInt() != 0) {
55+
val firstLba = buffer.getLong(entry_offset + FIRST_LBA_OFFSET)
56+
val entry = PartitionTableEntry(-1, // Unknown
57+
firstLba,
58+
buffer.getLong(entry_offset + LAST_LBA_OFFSET) - firstLba)
59+
60+
result.partitions.add(entry)
61+
62+
entry_offset += ENTRY_SIZE
63+
}
64+
65+
66+
return result
67+
}
68+
}
69+
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.github.mjdev.libaums.partition.gpt
2+
3+
import me.jahnen.libaums.core.driver.BlockDeviceDriver
4+
import me.jahnen.libaums.core.partition.PartitionTable
5+
import me.jahnen.libaums.core.partition.PartitionTableFactory
6+
7+
8+
class GPTCreator: PartitionTableFactory.PartitionTableCreator {
9+
override fun read(blockDevice: BlockDeviceDriver): PartitionTable? = GPT.read(blockDevice)
10+
}

‎libaums/src/main/java/me/jahnen/libaums/core/driver/ByteBlockDevice.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import java.nio.ByteBuffer
99
* and [ByteBlockDevice.read]. Uses [BlockDeviceDriver.getBlockSize]
1010
* to calculate device offsets.
1111
*/
12-
open class ByteBlockDevice @JvmOverloads constructor(private val targetBlockDevice: BlockDeviceDriver, private val logicalOffsetToAdd: Int = 0) : BlockDeviceDriver {
12+
open class ByteBlockDevice @JvmOverloads constructor(private val targetBlockDevice: BlockDeviceDriver, private val logicalOffsetToAdd: Long = 0) : BlockDeviceDriver {
1313
override val blockSize: Int
1414
get() = targetBlockDevice.blockSize
1515

‎libaums/src/main/java/me/jahnen/libaums/core/partition/PartitionTableEntry.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ class PartitionTableEntry
2828
* Construct a new PartitionTableEntry with the given information.
2929
*
3030
* @param partitionType
31-
* The file system type of the partition (eg. FAT32).
31+
* The file system type of the partition (eg. FAT32). -1 if unknown
3232
* @param logicalBlockAddress
3333
* The logical block address on the device where this partition
3434
* starts.
3535
* @param totalNumberOfSectors
3636
* The total numbers of sectors occupied by the partition.
3737
*/
38-
(partitionType: Int, logicalBlockAddress: Int, totalNumberOfSectors: Int) {
38+
(partitionType: Int, logicalBlockAddress: Long, totalNumberOfSectors: Long) {
3939

4040
/**
4141
*
@@ -48,15 +48,15 @@ class PartitionTableEntry
4848
* @return The logical block address where this partitions starts on the
4949
* device.
5050
*/
51-
var logicalBlockAddress: Int = 0
51+
var logicalBlockAddress: Long = 0
5252
internal set
5353
/**
5454
*
5555
* @return The total numbers of sectors occupied by this partition. This
5656
* value is often unused because the same information is also stored
5757
* in the specific file system.
5858
*/
59-
var totalNumberOfSectors: Int = 0
59+
var totalNumberOfSectors: Long = 0
6060
internal set
6161

6262
init {

‎libaums/src/main/java/me/jahnen/libaums/core/partition/PartitionTableFactory.kt

+7
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717

1818
package me.jahnen.libaums.core.partition
1919

20+
import android.util.Log
21+
import com.github.mjdev.libaums.partition.gpt.GPTCreator
2022
import me.jahnen.libaums.core.driver.BlockDeviceDriver
2123
import me.jahnen.libaums.core.partition.fs.FileSystemPartitionTableCreator
24+
import me.jahnen.libaums.core.partition.mbr.MasterBootRecord
2225
import me.jahnen.libaums.core.partition.mbr.MasterBootRecordCreator
2326
import java.io.IOException
2427
import java.util.*
@@ -29,6 +32,7 @@ import java.util.*
2932
* @author mjahnen
3033
*/
3134
object PartitionTableFactory {
35+
private val TAG = PartitionTableFactory::class.java.simpleName
3236

3337
private val partitionTables = ArrayList<PartitionTableCreator>()
3438

@@ -41,6 +45,7 @@ object PartitionTableFactory {
4145

4246
init {
4347
registerPartitionTable(FileSystemPartitionTableCreator())
48+
registerPartitionTable(GPTCreator())
4449
registerPartitionTable(MasterBootRecordCreator())
4550
}
4651

@@ -60,8 +65,10 @@ object PartitionTableFactory {
6065
for (creator in partitionTables) {
6166
val table = creator.read(blockDevice)
6267
if (table != null) {
68+
Log.d(TAG, "Found partition table ${creator::class.java.simpleName}")
6369
return table
6470
}
71+
Log.d(TAG, "${creator::class.java.simpleName} returned null")
6572
}
6673

6774
throw UnsupportedPartitionTableException()

‎libaums/src/main/java/me/jahnen/libaums/core/partition/fs/FileSystemPartitionTable.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class FileSystemPartitionTable(blockDevice: BlockDeviceDriver, fs: FileSystem) :
2424

2525
init {
2626
Log.i(TAG, "Found a device without partition table, yay!")
27-
val totalNumberOfSectors = fs.capacity.toInt() / blockDevice.blockSize
27+
val totalNumberOfSectors = fs.capacity / blockDevice.blockSize
2828
if (fs.capacity % blockDevice.blockSize != 0L) {
2929
Log.w(TAG, "fs capacity is not multiple of block size")
3030
}

‎libaums/src/main/java/me/jahnen/libaums/core/partition/mbr/MasterBootRecord.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class MasterBootRecord private constructor() : PartitionTable {
111111
}
112112

113113
val entry = PartitionTableEntry(type,
114-
buffer.getInt(offset + 8), buffer.getInt(offset + 12))
114+
buffer.getInt(offset + 8).toLong(), buffer.getInt(offset + 12).toLong())
115115

116116
result.partitions.add(entry)
117117
}

‎libaums/src/main/java/me/jahnen/libaums/core/usb/AndroidUsbCommunication.kt

+9-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal abstract class AndroidUsbCommunication(
1717

1818
private var isNativeInited: Boolean = false
1919
var deviceConnection: UsbDeviceConnection? = null
20-
private var isClosed = false
20+
protected var isClosed = false
2121

2222
init {
2323
initNativeLibrary()
@@ -49,10 +49,14 @@ internal abstract class AndroidUsbCommunication(
4949
}
5050

5151
override fun controlTransfer(requestType: Int, request: Int, value: Int, index: Int, buffer: ByteArray, length: Int): Int {
52+
require(!isClosed) { "device is closed" }
53+
5254
return deviceConnection!!.controlTransfer(requestType, request, value, index, buffer, length, TRANSFER_TIMEOUT)
5355
}
5456

5557
override fun resetDevice() {
58+
require(!isClosed) { "device is closed" }
59+
5660
Log.d(TAG, "Performing native reset")
5761

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

7276
override fun clearFeatureHalt(endpoint: UsbEndpoint) {
77+
require(!isClosed) { "device is closed" }
78+
7379
Log.w(TAG, "Clearing halt on endpoint $endpoint (direction ${endpoint.direction})")
7480
val result = clearHaltNative(deviceConnection!!.fileDescriptor, endpoint.address)
7581
if (!result) {
@@ -90,6 +96,8 @@ internal abstract class AndroidUsbCommunication(
9096
}
9197

9298
override fun close() {
99+
require(!isClosed) { "device is already closed" }
100+
93101
Log.d(TAG, "close device")
94102
closeUsbConnection()
95103
isClosed = true

‎libaums/src/main/java/me/jahnen/libaums/core/usb/HoneyCombMr1Communication.kt

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ internal class HoneyCombMr1Communication(
2525

2626
@Throws(IOException::class)
2727
override fun bulkOutTransfer(src: ByteBuffer): Int {
28+
require(!isClosed) { "device is closed" }
29+
2830
val offset = src.position()
2931

3032
if (offset == 0) {
@@ -54,6 +56,8 @@ internal class HoneyCombMr1Communication(
5456

5557
@Throws(IOException::class)
5658
override fun bulkInTransfer(dest: ByteBuffer): Int {
59+
require(!isClosed) { "device is closed" }
60+
5761
val offset = dest.position()
5862

5963
if (offset == 0) {

‎libaums/src/main/java/me/jahnen/libaums/core/usb/JellyBeanMr2Communication.kt

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ internal class JellyBeanMr2Communication(
3030

3131
@Throws(IOException::class)
3232
override fun bulkOutTransfer(src: ByteBuffer): Int {
33+
require(!isClosed) { "device is closed" }
34+
3335
val result = deviceConnection!!.bulkTransfer(outEndpoint,
3436
src.array(), src.position(), src.remaining(), UsbCommunication.TRANSFER_TIMEOUT)
3537

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

4749
@Throws(IOException::class)
4850
override fun bulkInTransfer(dest: ByteBuffer): Int {
51+
require(!isClosed) { "device is closed" }
52+
4953
val result = deviceConnection!!.bulkTransfer(inEndpoint,
5054
dest.array(), dest.position(), dest.remaining(), UsbCommunication.TRANSFER_TIMEOUT)
5155

‎libusbcommunication/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Refer to the following blog where someone claims that LPGL cannot be used in clo
3838
#### Inclusion in your build.gradle
3939

4040
```ruby
41-
implementation 'me.jahnen.libaums:libusbcommunication:0.2.4'
41+
implementation 'me.jahnen.libaums:libusbcommunication:0.3.0'
4242
```
4343

4444
### Activate libusb communication

‎libusbcommunication/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ String libusbDir = props['libusb.dir']
88

99
ext {
1010
PUBLISH_GROUP_ID = 'me.jahnen.libaums'
11-
PUBLISH_VERSION = '0.2.4'
11+
PUBLISH_VERSION = '0.3.0'
1212
PUBLISH_ARTIFACT_ID = 'libusbcommunication'
1313
}
1414

‎libusbcommunication/src/main/java/me/jahnen/libaums/libusbcommunication/LibusbCommunication.kt

+20-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class LibusbCommunication(
2828
private val libUsbHandle: Long
2929
get() = libUsbHandleArray[0]
3030
private var deviceConnection: UsbDeviceConnection?
31+
private var closed = false
3132

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

6162
override fun bulkOutTransfer(src: ByteBuffer): Int {
63+
require(!closed) { "device is closed" }
64+
6265
val transferred = nativeBulkTransfer(
6366
libUsbHandle, outEndpoint.address, src.array(), src.position(), src.remaining(),
6467
TRANSFER_TIMEOUT
@@ -74,6 +77,8 @@ class LibusbCommunication(
7477
}
7578

7679
override fun bulkInTransfer(dest: ByteBuffer): Int {
80+
require(!closed) { "device is closed" }
81+
7782
val transferred = nativeBulkTransfer(
7883
libUsbHandle, inEndpoint.address, dest.array(), dest.position(), dest.remaining(),
7984
TRANSFER_TIMEOUT
@@ -89,6 +94,8 @@ class LibusbCommunication(
8994
}
9095

9196
override fun controlTransfer(requestType: Int, request: Int, value: Int, index: Int, buffer: ByteArray, length: Int): Int {
97+
require(!closed) { "device is closed" }
98+
9299
val ret = nativeControlTransfer(libUsbHandle, requestType, request, value, index, buffer, length, TRANSFER_TIMEOUT)
93100
if (ret < 0) {
94101
throw LibusbException("libusb control transfer failed", LibusbError.fromCode(ret))
@@ -97,6 +104,8 @@ class LibusbCommunication(
97104
}
98105

99106
override fun resetDevice() {
107+
require(!closed) { "device is closed" }
108+
100109
if (!deviceConnection!!.releaseInterface(usbInterface)) {
101110
Log.w(TAG, "Failed to release interface, errno: ${ErrNo.errno} ${ErrNo.errstr}")
102111
}
@@ -118,14 +127,22 @@ class LibusbCommunication(
118127
}
119128

120129
override fun clearFeatureHalt(endpoint: UsbEndpoint) {
130+
require(!closed) { "device is closed" }
131+
121132
val ret = nativeClearHalt(libUsbHandle, endpoint.address)
122133
Log.d(TAG, "libusb clearFeatureHalt returned $ret: ${LibusbError.fromCode(ret).message}")
123134
}
124135

125136
override fun close() {
126-
deviceConnection!!.releaseInterface(usbInterface)
127-
nativeClose(libUsbHandle, usbInterface.id)
128-
deviceConnection!!.close()
137+
require(!closed) { "device is already closed" }
138+
139+
try {
140+
deviceConnection!!.releaseInterface(usbInterface)
141+
nativeClose(libUsbHandle, usbInterface.id)
142+
deviceConnection!!.close()
143+
} finally {
144+
closed = true
145+
}
129146
}
130147

131148
companion object {

0 commit comments

Comments
 (0)
Please sign in to comment.