-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: John Sanpe <[email protected]>
- Loading branch information
Showing
2 changed files
with
200 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,194 @@ | ||
#include <bfdev.h> | ||
#include <unistd.h> | ||
#include <sys/fcntl.h> | ||
#include <xdbd_connection_usb.h> | ||
#include <linux/usb/ch9.h> | ||
|
||
#define USB_ADB_PATH "/dev/adb/usb" | ||
#define USB_FFS_ADB_PATH "/dev/usb-ffs/adb/" | ||
|
||
#define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH#x | ||
#define USB_FFS_ADB_EP0 USB_FFS_ADB_EP(ep0) | ||
#define USB_FFS_ADB_OUT USB_FFS_ADB_EP(ep1) | ||
#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2) | ||
|
||
#define ADB_DESCRIPTORS_MAGIC 1 | ||
#define ADB_STRINGS_MAGIC 2 | ||
#define ADB_CLASS 0xff | ||
#define ADB_SUBCLASS 0x42 | ||
#define ADB_PROTOCOL 0x1 | ||
#define ADB_INTERFACE "ADB Interface" | ||
|
||
#define MAX_PACKET_SIZE_FS 64 | ||
#define MAX_PACKET_SIZE_HS 512 | ||
|
||
struct adb_functionfs_descs_head { | ||
bfdev_le32 magic; | ||
bfdev_le32 length; | ||
bfdev_le32 fs_count; | ||
bfdev_le32 hs_count; | ||
} __bfdev_packed; | ||
|
||
struct adb_functionfs_strings_head { | ||
bfdev_le32 magic; | ||
bfdev_le32 length; | ||
bfdev_le32 str_count; | ||
bfdev_le32 lang_count; | ||
} __bfdev_packed; | ||
|
||
static const struct { | ||
struct adb_functionfs_descs_head header; | ||
struct { | ||
struct usb_interface_descriptor intf; | ||
struct usb_endpoint_descriptor source, sink; | ||
} __bfdev_packed fs_descs, hs_descs; | ||
} __bfdev_packed adb_descriptors = { | ||
.header = { | ||
.magic = ADB_DESCRIPTORS_MAGIC, | ||
.length = sizeof(adb_descriptors), | ||
.fs_count = 3, | ||
.hs_count = 3, | ||
}, | ||
.fs_descs = { | ||
.intf = { | ||
.bLength = sizeof(adb_descriptors.fs_descs.intf), | ||
.bDescriptorType = USB_DT_INTERFACE, | ||
.bInterfaceNumber = 0, | ||
.bNumEndpoints = 2, | ||
.bInterfaceClass = ADB_CLASS, | ||
.bInterfaceSubClass = ADB_SUBCLASS, | ||
.bInterfaceProtocol = ADB_PROTOCOL, | ||
.iInterface = 1, | ||
}, | ||
.source = { | ||
.bLength = sizeof(adb_descriptors.fs_descs.source), | ||
.bDescriptorType = USB_DT_ENDPOINT, | ||
.bEndpointAddress = 1 | USB_DIR_OUT, | ||
.bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
.wMaxPacketSize = MAX_PACKET_SIZE_FS, | ||
}, | ||
.sink = { | ||
.bLength = sizeof(adb_descriptors.fs_descs.sink), | ||
.bDescriptorType = USB_DT_ENDPOINT, | ||
.bEndpointAddress = 2 | USB_DIR_IN, | ||
.bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
.wMaxPacketSize = MAX_PACKET_SIZE_FS, | ||
}, | ||
}, | ||
.hs_descs = { | ||
.intf = { | ||
.bLength = sizeof(adb_descriptors.hs_descs.intf), | ||
.bDescriptorType = USB_DT_INTERFACE, | ||
.bInterfaceNumber = 0, | ||
.bNumEndpoints = 2, | ||
.bInterfaceClass = ADB_CLASS, | ||
.bInterfaceSubClass = ADB_SUBCLASS, | ||
.bInterfaceProtocol = ADB_PROTOCOL, | ||
.iInterface = 1, | ||
}, | ||
.source = { | ||
.bLength = sizeof(adb_descriptors.hs_descs.source), | ||
.bDescriptorType = USB_DT_ENDPOINT, | ||
.bEndpointAddress = 1 | USB_DIR_OUT, | ||
.bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
.wMaxPacketSize = MAX_PACKET_SIZE_HS, | ||
}, | ||
.sink = { | ||
.bLength = sizeof(adb_descriptors.hs_descs.sink), | ||
.bDescriptorType = USB_DT_ENDPOINT, | ||
.bEndpointAddress = 2 | USB_DIR_IN, | ||
.bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
.wMaxPacketSize = MAX_PACKET_SIZE_HS, | ||
}, | ||
}, | ||
}; | ||
|
||
static const struct { | ||
struct adb_functionfs_strings_head header; | ||
struct { | ||
bfdev_le16 code; | ||
const char str[sizeof(ADB_INTERFACE)]; | ||
} __bfdev_packed lang; | ||
} __bfdev_packed adb_strings = { | ||
.header = { | ||
.magic = ADB_STRINGS_MAGIC, | ||
.length = sizeof(adb_strings), | ||
.str_count = 1, | ||
.lang_count = 1, | ||
}, | ||
.lang = { | ||
.code = 0x0409, | ||
.str = ADB_INTERFACE, | ||
}, | ||
}; | ||
|
||
struct adb_connection { | ||
int control; | ||
int bulk_out; | ||
int bulk_in; | ||
}; | ||
|
||
static int | ||
adb_init_send(struct adb_connection *conn) | ||
{ | ||
int retval; | ||
|
||
retval = write(conn->control, &adb_descriptors, sizeof(adb_descriptors)); | ||
if (retval != sizeof(adb_descriptors)) { | ||
bfdev_log_err("adbd: %s write descriptors failed: %m\n", USB_FFS_ADB_EP0); | ||
return retval; | ||
} | ||
|
||
retval = write(conn->control, &adb_strings, sizeof(adb_strings)); | ||
if (retval != sizeof(adb_strings)) { | ||
bfdev_log_err("adbd: %s write strings failed: %m\n", USB_FFS_ADB_EP0); | ||
return retval; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int | ||
adb_init_connection(struct adb_connection *conn) | ||
{ | ||
int retval; | ||
|
||
retval = open(USB_FFS_ADB_EP0, O_RDWR); | ||
if (retval < 0) { | ||
bfdev_log_err("adbd: %s open failed: %m\n", USB_FFS_ADB_EP0); | ||
goto failed; | ||
} | ||
conn->control = retval; | ||
|
||
retval = open(USB_FFS_ADB_OUT, O_RDWR); | ||
if (retval < 0) { | ||
bfdev_log_err("adbd: %s open failed: %m\n", USB_FFS_ADB_OUT); | ||
goto failed; | ||
} | ||
conn->bulk_out = retval; | ||
|
||
retval = open(USB_FFS_ADB_IN, O_RDWR); | ||
if (retval < 0) { | ||
bfdev_log_err("adbd: %s open failed: %m\n", USB_FFS_ADB_IN); | ||
goto failed; | ||
} | ||
conn->bulk_in = retval; | ||
|
||
retval = adb_init_send(conn); | ||
if (retval) { | ||
bfdev_log_err("adbd: init send failed\n"); | ||
goto failed; | ||
} | ||
|
||
return 0; | ||
|
||
failed: | ||
if (conn->control) | ||
close(conn->control); | ||
if (conn->bulk_out) | ||
close(conn->bulk_out); | ||
if (conn->bulk_in) | ||
close(conn->bulk_in); | ||
|
||
return retval; | ||
} |