mirror of
https://github.com/libimobiledevice/libplist
synced 2026-06-08 15:29:34 +00:00
migrate usbmux.c.
This commit is contained in:
@@ -32,18 +32,19 @@ extern "C" {
|
||||
//general errors
|
||||
#define IPHONE_E_SUCCESS 0
|
||||
#define IPHONE_E_INVALID_ARG -1
|
||||
#define IPHONE_E_NO_DEVICE -2
|
||||
#define IPHONE_E_TIMEOUT -3
|
||||
#define IPHONE_E_NOT_ENOUGH_DATA -4
|
||||
#define IPHONE_E_BAD_HEADER -5
|
||||
#define IPHONE_E_UNKNOWN_ERROR -2
|
||||
#define IPHONE_E_NO_DEVICE -3
|
||||
#define IPHONE_E_TIMEOUT -4
|
||||
#define IPHONE_E_NOT_ENOUGH_DATA -5
|
||||
#define IPHONE_E_BAD_HEADER -6
|
||||
|
||||
//lockdownd specific error
|
||||
#define IPHONE_E_INVALID_CONF -6
|
||||
#define IPHONE_E_PAIRING_FAILED -7
|
||||
#define IPHONE_E_SSL_ERROR -8
|
||||
#define IPHONE_E_INVALID_CONF -7
|
||||
#define IPHONE_E_PAIRING_FAILED -8
|
||||
#define IPHONE_E_SSL_ERROR -9
|
||||
|
||||
//afc specific error
|
||||
#define IPHONE_E_NO_SUCH_FILE -9
|
||||
#define IPHONE_E_NO_SUCH_FILE -10
|
||||
|
||||
struct iphone_device_int;
|
||||
typedef struct iphone_device_int *iphone_device_t;
|
||||
|
||||
+1
-2
@@ -42,7 +42,6 @@ int iphone_get_device ( iphone_device_t *device ){
|
||||
struct usb_bus *bus, *busses;
|
||||
struct usb_device *dev;
|
||||
iphone_device_t phone = (iphone_device_t)malloc(sizeof(struct iphone_device_int));
|
||||
usbmux_version_header *version = version_header();
|
||||
|
||||
// Initialize the struct
|
||||
phone->device = NULL;
|
||||
@@ -126,7 +125,7 @@ int iphone_get_device ( iphone_device_t *device ){
|
||||
if (debug) fprintf(stderr, "get_iPhone(): Unknown error.\n");
|
||||
free_iPhone(phone);
|
||||
free(version);
|
||||
return IPHONE_E_NO_DEVICE; // if it got to this point it's gotta be bad
|
||||
return IPHONE_E_UNKNOWN_ERROR; // if it got to this point it's gotta be bad
|
||||
}
|
||||
|
||||
/** Cleans up an iPhone structure, then frees the structure itself.
|
||||
|
||||
+3
-3
@@ -77,8 +77,8 @@ char *lockdownd_generate_hostid() {
|
||||
iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) {
|
||||
if (!phone) return NULL;
|
||||
iphone_lckd_client_t control = (iphone_lckd_client_t)malloc(sizeof(struct iphone_lckd_client_int));
|
||||
control->connection = mux_connect(phone, 0x0a00, 0xf27e);
|
||||
if (!control->connection) {
|
||||
|
||||
if (IPHONE_E_SUCCESS != iphone_mux_new_client ( phone, 0x0a00, 0xf27e, &control->connection)) {
|
||||
free(control);
|
||||
return NULL;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ void iphone_lckd_free_client( iphone_lckd_client_t client ) {
|
||||
mux_close_connection(client->connection);
|
||||
}
|
||||
|
||||
if (client->ssl_session) gnutls_deinit(*control->ssl_session);
|
||||
if (client->ssl_session) gnutls_deinit(*client->ssl_session);
|
||||
free(client->ssl_session);
|
||||
free(client);
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@
|
||||
|
||||
|
||||
struct iphone_lckd_client_int {
|
||||
usbmux_connection *connection;
|
||||
iphone_umux_client_t connection;
|
||||
gnutls_session_t *ssl_session;
|
||||
int in_SSL;
|
||||
char *gtls_buffer_hack;
|
||||
|
||||
+89
-81
@@ -29,8 +29,8 @@
|
||||
|
||||
extern int debug;
|
||||
|
||||
static usbmux_connection **connlist = NULL;
|
||||
static int connections = 0;
|
||||
static iphone_umux_client_t *connlist = NULL;
|
||||
static int clients = 0;
|
||||
|
||||
/** Creates a USBMux packet for the given set of ports.
|
||||
*
|
||||
@@ -76,10 +76,10 @@ usbmux_version_header *version_header() {
|
||||
*
|
||||
* @param connection The connection to delete from the tracking list.
|
||||
*/
|
||||
void delete_connection(usbmux_connection *connection) {
|
||||
usbmux_connection **newlist = (usbmux_connection**)malloc(sizeof(usbmux_connection*) * (connections - 1));
|
||||
void delete_connection(iphone_umux_client_t connection) {
|
||||
iphone_umux_client_t *newlist = (iphone_umux_client_t*)malloc(sizeof(iphone_umux_client_t) * (clients - 1));
|
||||
int i = 0, j = 0;
|
||||
for (i = 0; i < connections; i++) {
|
||||
for (i = 0; i < clients; i++) {
|
||||
if (connlist[i] == connection) continue;
|
||||
else {
|
||||
newlist[j] = connlist[i];
|
||||
@@ -88,7 +88,7 @@ void delete_connection(usbmux_connection *connection) {
|
||||
}
|
||||
free(connlist);
|
||||
connlist = newlist;
|
||||
connections--;
|
||||
clients--;
|
||||
if (connection->recv_buffer) free(connection->recv_buffer);
|
||||
if (connection->header) free(connection->header);
|
||||
connection->r_len = 0;
|
||||
@@ -101,59 +101,64 @@ void delete_connection(usbmux_connection *connection) {
|
||||
* @param connection The connection to add to the global list of connections.
|
||||
*/
|
||||
|
||||
void add_connection(usbmux_connection *connection) {
|
||||
usbmux_connection **newlist = (usbmux_connection**)realloc(connlist, sizeof(usbmux_connection*) * (connections+1));
|
||||
newlist[connections] = connection;
|
||||
void add_connection(iphone_umux_client_t connection) {
|
||||
iphone_umux_client_t* newlist = (iphone_umux_client_t*)realloc(connlist, sizeof(iphone_umux_client_t) * (clients+1));
|
||||
newlist[clients] = connection;
|
||||
connlist = newlist;
|
||||
connections++;
|
||||
clients++;
|
||||
}
|
||||
|
||||
/** Initializes a connection on phone, with source port s_port and destination port d_port
|
||||
*
|
||||
* @param phone The iPhone to initialize a connection on.
|
||||
* @param s_port The source port
|
||||
* @param d_port The destination port -- 0xf27e for lockdownd.
|
||||
*
|
||||
* @return A mux TCP header for the connection which is used for tracking and data transfer.
|
||||
*/
|
||||
usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_port) {
|
||||
if (!phone || !s_port || !d_port) return NULL;
|
||||
* @param device The iPhone to initialize a connection on.
|
||||
* @param src_port The source port
|
||||
* @param dst_port The destination port -- 0xf27e for lockdownd.
|
||||
* @param client A mux TCP header for the connection which is used for tracking and data transfer.
|
||||
* @return IPHONE_E_SUCCESS on success, an error code otherwise.
|
||||
*/
|
||||
int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ){
|
||||
if (!device || !src_port || !dst_port)
|
||||
return IPHONE_E_INVALID_ARG;
|
||||
|
||||
int bytes = 0;
|
||||
// Initialize connection stuff
|
||||
usbmux_connection *new_connection = (usbmux_connection*)malloc(sizeof(usbmux_connection));
|
||||
new_connection->header = new_mux_packet(s_port, d_port);
|
||||
iphone_umux_client_t new_connection = (iphone_umux_client_t)malloc(sizeof(struct iphone_umux_client_int));
|
||||
new_connection->header = new_mux_packet(src_port, dst_port);
|
||||
|
||||
// blargg
|
||||
if (new_connection && new_connection->header) {
|
||||
new_connection->header->tcp_flags = 0x02;
|
||||
new_connection->header->length = htonl(new_connection->header->length);
|
||||
new_connection->header->length16 = htons(new_connection->header->length16);
|
||||
|
||||
if (send_to_phone(phone, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) {
|
||||
if (send_to_phone(device, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) {
|
||||
usbmux_tcp_header *response;
|
||||
response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header));
|
||||
bytes = recv_from_phone(phone, (char*)response, sizeof(*response));
|
||||
bytes = recv_from_phone(device, (char*)response, sizeof(*response));
|
||||
if (response->tcp_flags != 0x12) {
|
||||
free(response);
|
||||
return NULL;
|
||||
return IPHONE_E_UNKNOWN_ERROR;
|
||||
} else {
|
||||
free(response);
|
||||
|
||||
if (debug) printf("mux_connect: connection success\n");
|
||||
new_connection->header->tcp_flags = 0x10;
|
||||
new_connection->header->scnt = 1;
|
||||
new_connection->header->ocnt = 1;
|
||||
new_connection->phone = phone;
|
||||
new_connection->phone = device;
|
||||
new_connection->recv_buffer = NULL;
|
||||
new_connection->r_len = 0;
|
||||
add_connection(new_connection);
|
||||
return new_connection;
|
||||
*client = new_connection;
|
||||
return IPHONE_E_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
return IPHONE_E_NOT_ENOUGH_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
// if we get to this point it's probably bad
|
||||
return NULL;
|
||||
return IPHONE_E_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
/** Cleans up the given USBMux connection.
|
||||
@@ -161,56 +166,59 @@ usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_po
|
||||
*
|
||||
* @param connection The connection to close.
|
||||
*/
|
||||
void mux_close_connection(usbmux_connection *connection) {
|
||||
if (!connection || !connection->phone) return;
|
||||
void iphone_mux_free_client ( iphone_umux_client_t client ) {
|
||||
if (!client || !client->phone) return;
|
||||
|
||||
connection->header->tcp_flags = 0x04;
|
||||
connection->header->scnt = htonl(connection->header->scnt);
|
||||
connection->header->ocnt = htonl(connection->header->ocnt);
|
||||
client->header->tcp_flags = 0x04;
|
||||
client->header->scnt = htonl(client->header->scnt);
|
||||
client->header->ocnt = htonl(client->header->ocnt);
|
||||
int bytes = 0;
|
||||
|
||||
bytes = usb_bulk_write(connection->phone->device, BULKOUT, (char*)connection->header, sizeof(usbmux_tcp_header), 800);
|
||||
bytes = usb_bulk_write(client->phone->device, BULKOUT, (char*)client->header, sizeof(usbmux_tcp_header), 800);
|
||||
if(debug && bytes < 0)
|
||||
printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror());
|
||||
|
||||
bytes = usb_bulk_read(connection->phone->device, BULKIN, (char*)connection->header, sizeof(usbmux_tcp_header), 800);
|
||||
bytes = usb_bulk_read(client->phone->device, BULKIN, (char*)client->header, sizeof(usbmux_tcp_header), 800);
|
||||
if(debug && bytes < 0)
|
||||
printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror());
|
||||
|
||||
delete_connection(connection);
|
||||
delete_connection(client);
|
||||
}
|
||||
|
||||
|
||||
/** Sends the given data over the selected connection.
|
||||
*
|
||||
* @param connection The connection we're sending data on.
|
||||
*
|
||||
* @param phone The iPhone to send to.
|
||||
* @param client The client we're sending data on.
|
||||
* @param data A pointer to the data to send.
|
||||
* @param datalen How much data we're sending.
|
||||
*
|
||||
* @return The number of bytes sent, minus the header (28), or -1 on error.
|
||||
*/
|
||||
int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) {
|
||||
if (!connection->phone || !connection || !data || datalen == 0) return -1;
|
||||
// connection->scnt and connection->ocnt should already be in host notation...
|
||||
|
||||
int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen ) {
|
||||
if (!client->phone || !client || !data || datalen == 0) return -1;
|
||||
// client->scnt and client->ocnt should already be in host notation...
|
||||
// we don't need to change them juuuust yet.
|
||||
int bytes = 0;
|
||||
if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen);
|
||||
char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding
|
||||
// Set the length and pre-emptively htonl/htons it
|
||||
connection->header->length = htonl(sizeof(usbmux_tcp_header) + datalen);
|
||||
connection->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen);
|
||||
client->header->length = htonl(sizeof(usbmux_tcp_header) + datalen);
|
||||
client->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen);
|
||||
|
||||
// Put scnt and ocnt into big-endian notation
|
||||
connection->header->scnt = htonl(connection->header->scnt);
|
||||
connection->header->ocnt = htonl(connection->header->ocnt);
|
||||
client->header->scnt = htonl(client->header->scnt);
|
||||
client->header->ocnt = htonl(client->header->ocnt);
|
||||
// Concatenation of stuff in the buffer.
|
||||
memcpy(buffer, connection->header, sizeof(usbmux_tcp_header));
|
||||
memcpy(buffer, client->header, sizeof(usbmux_tcp_header));
|
||||
memcpy(buffer+sizeof(usbmux_tcp_header), data, datalen);
|
||||
|
||||
// We have a buffer full of data, we should now send it to the phone.
|
||||
if (debug) printf("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header)+datalen, buffer);
|
||||
|
||||
|
||||
bytes = send_to_phone(connection->phone, buffer, sizeof(usbmux_tcp_header)+datalen);
|
||||
bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen);
|
||||
if (debug) printf("mux_send: sent %i bytes!\n", bytes);
|
||||
// Now that we've sent it off, we can clean up after our sloppy selves.
|
||||
if (debug) {
|
||||
@@ -222,12 +230,12 @@ int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) {
|
||||
|
||||
if (buffer) free(buffer);
|
||||
// Re-calculate scnt and ocnt
|
||||
connection->header->scnt = ntohl(connection->header->scnt) + datalen;
|
||||
connection->header->ocnt = ntohl(connection->header->ocnt);
|
||||
client->header->scnt = ntohl(client->header->scnt) + datalen;
|
||||
client->header->ocnt = ntohl(client->header->ocnt);
|
||||
|
||||
// Revert lengths
|
||||
connection->header->length = ntohl(connection->header->length);
|
||||
connection->header->length16 = ntohs(connection->header->length16);
|
||||
client->header->length = ntohl(client->header->length);
|
||||
client->header->length16 = ntohs(client->header->length16);
|
||||
|
||||
// Now return the bytes.
|
||||
if (bytes < sizeof(usbmux_tcp_header)+datalen) {
|
||||
@@ -247,52 +255,52 @@ int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) {
|
||||
*
|
||||
* @return How many bytes were read, or -1 if something bad happens.
|
||||
*/
|
||||
int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
|
||||
int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen ) {
|
||||
/*
|
||||
* Order of operation:
|
||||
* 1.) Check if the connection has a pre-received buffer.
|
||||
* 1.) Check if the client has a pre-received buffer.
|
||||
* 2.) If so, fill data with the buffer, as much as needed.
|
||||
* a.) Return quickly if the buffer has enough
|
||||
* b.) If the buffer is only part of the datalen, get the rest of datalen (and if we can't, just return)
|
||||
* 3.) If not, receive directly from the phone.
|
||||
* a.) Check incoming packet's ports. If proper, follow proper buffering and receiving operation.
|
||||
* b.) If not, find the connection the ports belong to and fill that connection's buffer, then return mux_recv with the same args to try again.
|
||||
* b.) If not, find the client the ports belong to and fill that client's buffer, then return mux_recv with the same args to try again.
|
||||
*/
|
||||
if (debug) printf("mux_recv: datalen == %i\n", datalen);
|
||||
int bytes = 0, i = 0, complex = 0, offset = 0;
|
||||
char *buffer = NULL;
|
||||
usbmux_tcp_header *header = NULL;
|
||||
|
||||
if (connection->recv_buffer) {
|
||||
if (connection->r_len >= datalen) {
|
||||
memcpy(data, connection->recv_buffer, datalen);
|
||||
if (connection->r_len == datalen) {
|
||||
if (client->recv_buffer) {
|
||||
if (client->r_len >= datalen) {
|
||||
memcpy(data, client->recv_buffer, datalen);
|
||||
if (client->r_len == datalen) {
|
||||
// reset everything
|
||||
free(connection->recv_buffer);
|
||||
connection->r_len = 0;
|
||||
connection->recv_buffer = NULL;
|
||||
free(client->recv_buffer);
|
||||
client->r_len = 0;
|
||||
client->recv_buffer = NULL;
|
||||
} else {
|
||||
buffer = (char*)malloc(sizeof(char) * (connection->r_len - datalen));
|
||||
memcpy(buffer, connection->recv_buffer+datalen, (connection->r_len - datalen));
|
||||
connection->r_len -= datalen;
|
||||
free(connection->recv_buffer);
|
||||
connection->recv_buffer = buffer;
|
||||
buffer = (char*)malloc(sizeof(char) * (client->r_len - datalen));
|
||||
memcpy(buffer, client->recv_buffer+datalen, (client->r_len - datalen));
|
||||
client->r_len -= datalen;
|
||||
free(client->recv_buffer);
|
||||
client->recv_buffer = buffer;
|
||||
}
|
||||
|
||||
// Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above.
|
||||
return datalen;
|
||||
} else {
|
||||
memcpy(data, connection->recv_buffer, connection->r_len);
|
||||
free(connection->recv_buffer); // don't need to deal with anymore, but...
|
||||
offset = connection->r_len; // see #2b, above
|
||||
connection->r_len = 0;
|
||||
memcpy(data, client->recv_buffer, client->r_len);
|
||||
free(client->recv_buffer); // don't need to deal with anymore, but...
|
||||
offset = client->r_len; // see #2b, above
|
||||
client->r_len = 0;
|
||||
}
|
||||
} // End of what to do if we have a pre-buffer. See #1 and #2 above.
|
||||
|
||||
buffer = (char*)malloc(sizeof(char) * 131072); // make sure we get enough ;)
|
||||
|
||||
// See #3.
|
||||
bytes = recv_from_phone(connection->phone, buffer, 131072);
|
||||
bytes = recv_from_phone(client->phone, buffer, 131072);
|
||||
if (bytes < 28) {
|
||||
free(buffer);
|
||||
if (debug) printf("mux_recv: Did not even get the header.\n");
|
||||
@@ -300,10 +308,10 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
|
||||
}
|
||||
|
||||
header = (usbmux_tcp_header*)buffer;
|
||||
if (header->sport != connection->header->dport || header->dport != connection->header->sport) {
|
||||
if (header->sport != client->header->dport || header->dport != client->header->sport) {
|
||||
// Ooooops -- we got someone else's packet.
|
||||
// We gotta stick it in their buffer. (Take that any old way you want ;) )
|
||||
for (i = 0; i < connections; i++) {
|
||||
for (i = 0; i < clients; i++) {
|
||||
if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) {
|
||||
// we have a winner.
|
||||
char *nfb = (char*)malloc(sizeof(char) * (connlist[i]->r_len + (bytes - 28)));
|
||||
@@ -312,7 +320,7 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
|
||||
free(connlist[i]->recv_buffer);
|
||||
}
|
||||
connlist[i]->r_len += bytes - 28;
|
||||
//connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * connection->r_len); // grow their buffer
|
||||
//connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * client->r_len); // grow their buffer
|
||||
connlist[i]->recv_buffer = nfb;
|
||||
nfb = NULL; // A cookie for you if you can guess what "nfb" means.
|
||||
complex = connlist[i]->r_len - (bytes - 28);
|
||||
@@ -324,7 +332,7 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
|
||||
// Free our buffer and continue.
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
return mux_recv(connection, data, datalen); // recurse back in to try again
|
||||
return mux_recv(client, data, datalen); // recurse back in to try again
|
||||
}
|
||||
|
||||
// The packet was absolutely meant for us if it hits this point.
|
||||
@@ -333,18 +341,18 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
|
||||
if ((bytes-28) > datalen) {
|
||||
// Copy what we need into the data, buffer the rest because we can.
|
||||
memcpy(data+offset, buffer+28, datalen); // data+offset: see #2b, above
|
||||
complex = connection->r_len + (bytes-28) - datalen;
|
||||
connection->recv_buffer = (char*)realloc(connection->recv_buffer, (sizeof(char) * complex));
|
||||
connection->r_len = complex;
|
||||
complex = connection->r_len - (bytes-28) - datalen;
|
||||
memcpy(connection->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen);
|
||||
complex = client->r_len + (bytes-28) - datalen;
|
||||
client->recv_buffer = (char*)realloc(client->recv_buffer, (sizeof(char) * complex));
|
||||
client->r_len = complex;
|
||||
complex = client->r_len - (bytes-28) - datalen;
|
||||
memcpy(client->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen);
|
||||
free(buffer);
|
||||
connection->header->ocnt += bytes-28;
|
||||
client->header->ocnt += bytes-28;
|
||||
return datalen;
|
||||
} else {
|
||||
// Fill the data with what we have, and just return.
|
||||
memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above
|
||||
connection->header->ocnt += bytes-28;
|
||||
client->header->ocnt += bytes-28;
|
||||
free(buffer);
|
||||
return (bytes-28);
|
||||
}
|
||||
|
||||
+2
-7
@@ -43,12 +43,12 @@ typedef struct {
|
||||
uint16 window, nullnull, length16;
|
||||
} usbmux_tcp_header;
|
||||
|
||||
typedef struct {
|
||||
struct iphone_umux_client_int {
|
||||
usbmux_tcp_header *header;
|
||||
iphone_device_t phone;
|
||||
char *recv_buffer;
|
||||
int r_len;
|
||||
} usbmux_connection;
|
||||
};
|
||||
|
||||
usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port);
|
||||
|
||||
@@ -58,10 +58,5 @@ typedef struct {
|
||||
|
||||
usbmux_version_header *version_header();
|
||||
|
||||
usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_port);
|
||||
void mux_close_connection(usbmux_connection *connection);
|
||||
int mux_send(usbmux_connection *connection, const char *data, uint32 datalen);
|
||||
int mux_recv(usbmux_connection *connection, char *data, uint32 datalen);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user