This program is for an autonomous robot for the competition at the Hochschule Luzern. http://cruisingcrepe.wordpress.com/ We are one of the 32 teams. http://cruisingcrepe.wordpress.com/ The postition control is based on this Documentation: Control of Wheeled Mobile Robots: An Experimental Overview from Alessandro De Luca, Giuseppe Oriolo, Marilena Vendittelli. For more information see here: http://www.dis.uniroma1.it/~labrob/pub/papers/Ramsete01.pdf
Fork of autonomous Robot Android by
Diff: MicroBridge/ADB/Adb.cpp
- Revision:
- 17:f0a973f17917
diff -r b5d949136a21 -r f0a973f17917 MicroBridge/ADB/Adb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MicroBridge/ADB/Adb.cpp Fri May 03 06:30:46 2013 +0000 @@ -0,0 +1,891 @@ +/* + Copyright 2011 Niels Brouwers + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* Changed by Junichi Katsu */ + +#include <string.h> +#include <Adb.h> + +//#define DEBUG + +#define MAX_BUF_SIZE 128 + +#ifdef DEBUG +#define log(...) printf(__VA_ARGS__) +#else +#define log(...) do {} while(0) +#endif + +int input_ep; +int output_ep; +int _device; +int _configuration; +int _interfaceNumber; + +static Connection * firstConnection; +static boolean connected; +static int connectionLocalId = 1; +unsigned char readbuff[MAX_BUF_SIZE]; + +// Event handler callback function. +adb_eventHandler * eventHandler; + +ADB* _adb; +PacketBuffer recv_packet_buf(100,MAX_BUF_SIZE); +Ticker timer; + +int time_ms = 0; + + +void attime(void) +{ + time_ms++; +} + +int millis() +{ + return(time_ms); +} + +char *strdup(const char *src) +{ + char *p; + + if(src == NULL){ + return NULL; + } + + p = (char *)malloc(strlen(src) + 1); + if(p != NULL) strcpy(p, src); + return p; + +} + +/** + * Initialises the ADB protocol. This function initialises the USB layer underneath so no further setup is required. + */ +void ADB::init() +{ + recv_packet_buf.clear(); + + // Signal that we are not connected. + _device = 0; + connected = false; + + + // Initialise Usb host. + USBInit(); + + timer.attach_us(&attime, 1000); +} + +/** + * Sets the ADB event handler function. This function will be called by the ADB layer + * when interesting events occur, such as ADB connect/disconnect, connection open/close, and + * connection writes from the ADB device. + * + * @param handler event handler function. + */ +void ADB::setEventHandler(adb_eventHandler * handler) +{ + eventHandler = handler; +} + +/** + * Fires an ADB event. + * @param connection ADB connection. May be NULL in case of global connect/disconnect events. + * @param type event type. + * @param length payload length or zero if no payload. + * @param data payload data if relevant or NULL otherwise. + */ +void ADB::fireEvent(Connection * connection, adb_eventType type, uint16_t length, uint8_t * data) +{ + // Fire the global event handler, if set. + if (eventHandler!=NULL) + eventHandler(connection, type, length, data); + + // Fire the event handler of the connection in question, if relevant + if (connection!=NULL && connection->eventHandler!=NULL) + connection->eventHandler(connection, type, length, data); +} + +/** + * Adds a new ADB connection. The connection string is per ADB specs, for example "tcp:1234" opens a + * connection to tcp port 1234, and "shell:ls" outputs a listing of the phone root filesystem. Connections + * can be made persistent by setting reconnect to true. Persistent connections will be automatically + * reconnected when the USB cable is re-plugged in. Non-persistent connections will connect only once, + * and should never be used after they are closed. + * + * The connection string is copied into the Connection record and may not exceed ADB_CONNECTIONSTRING_LENGTH-1 + * characters. + * + * @param connectionString ADB connectionstring. I.e. "tcp:1234" or "shell:ls". + * @param reconnect true for automatic reconnect (persistent connections). + * @param handler event handler. + * @return an ADB connection record or NULL on failure (not enough slots or connection string too long). + */ +Connection * ADB::addConnection(const char * connectionString, boolean reconnect, adb_eventHandler * handler) +{ + + // Allocate a new ADB connection object + Connection * connection = (Connection*)malloc(sizeof(Connection)); + if (connection == NULL) return NULL; + + // Allocate memory for the connection string + connection->connectionString = (char*)strdup(connectionString); + if (connection->connectionString==NULL) + { + // Free the connection object and return null + free(connection); + return NULL; + } + + // Initialise the newly created object. + connection->localID = connectionLocalId ++; + connection->status = ADB_CLOSED; + connection->lastConnectionAttempt = 0; + connection->reconnect = reconnect; + connection->eventHandler = handler; + + // Add the connection to the linked list. Note that it's easier to just insert + // at position 0 because you don't have to traverse the list :) + connection->next = firstConnection; + firstConnection = connection; + + // Unable to find an empty spot, all connection slots in use. + return connection; +} + +/** + * Prints an ADB_message, for debugging purposes. + * @param message ADB message to print. + */ +#ifdef DEBUG +static void adb_printMessage(adb_message * message) +{ + switch(message->command) + { + case A_OKAY: + printf("OKAY message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1); + break; + case A_CLSE: + printf("CLSE message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1); + break; + case A_WRTE: + printf("WRTE message [%lx] %ld %ld, %ld bytes\r\n", message->command, message->arg0, message->arg1, message->data_length); + break; + case A_CNXN: + printf("CNXN message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1); + break; + case A_SYNC: + printf("SYNC message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1); + break; + case A_OPEN: + printf("OPEN message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1); + break; + default: + printf("WTF message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1); + break; + } +} +#endif + +/** + * Writes an empty message (without payload) to the ADB device. + * + * @param device USB device handle. + * @param command ADB command. + * @param arg0 first ADB argument (command dependent). + * @param arg0 second ADB argument (command dependent). + * @return error code or 0 for success. + */ +int ADB::writeEmptyMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1) +{ + adb_message message; + + message.command = command; + message.arg0 = arg0; + message.arg1 = arg1; + message.data_length = 0; + message.data_check = 0; + message.magic = command ^ 0xffffffff; + +#ifdef DEBUG + printf("OUT << "); adb_printMessage(&message); +#endif + + int r = USBBulkTransfer( device , output_ep , (uint8_t*)&message , sizeof(adb_message) ); + +#ifdef DEBUG + log("[writeMessage1] size:%d\r\n",r); + + int ii,jj; + uint8_t* buf = (uint8_t*)&message; + for(ii = 0 ; ii < r ; ii+=16) + { + for(jj = 0 ; jj < 16 ; jj+=2 ) + { + log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]); + if((ii+jj) > r) break; + } + log(" : "); + for(jj = 0 ; jj < 16 ; jj+=2 ) + { + log("%c%c",buf[ii+jj],buf[ii+jj+1]); + if((ii+jj) > r) break; + } + log("\r\n"); + if((ii+jj) > r) break; + } +#endif + + return r; +} + +/** + * Writes an ADB message with payload to the ADB device. + * + * @param device USB device handle. + * @param command ADB command. + * @param arg0 first ADB argument (command dependent). + * @param arg0 second ADB argument (command dependent). + * @param length payload length. + * @param data command payload. + * @return error code or 0 for success. + */ +int ADB::writeMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1, uint32_t length, uint8_t * data) +{ + adb_message message; + uint8_t msg[256]; + uint32_t count, sum = 0; + uint8_t * x; + + // Calculate data checksum + count = length; + x = data; + while(count-- > 0) sum += *x++; + + // Fill out the message record. + message.command = command; + message.arg0 = arg0; + message.arg1 = arg1; + message.data_length = length; + message.data_check = (sum); + message.magic = command ^ 0xffffffff; + +#ifdef DEBUG + printf("OUT << "); adb_printMessage(&message); +#endif + + int r = USBBulkTransfer( device , output_ep , (uint8_t*)&message , sizeof(adb_message) ); + + if (r<0) return r; + +#ifdef DEBUG + log("[writeMessage1] size:%d\r\n",r); + + int ii,jj; + uint8_t* buf = (uint8_t*)&message; + for(ii = 0 ; ii < r ; ii+=16) + { + for(jj = 0 ; jj < 16 ; jj+=2 ) + { + log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]); + if((ii+jj) > r) break; + } + log(" : "); + for(jj = 0 ; jj < 16 ; jj+=2 ) + { + log("%c%c",buf[ii+jj],buf[ii+jj+1]); + if((ii+jj) > r) break; + } + log("\r\n"); + if((ii+jj) > r) break; + } +#endif + + memcpy( msg , data , length ); + + r = USBBulkTransfer( device , output_ep , msg , length ); + log("USB SEND RET2:%d\r\n",r); + + if (r<0) return r; + +#ifdef DEBUG + log("[writeMessage2] size:%d\r\n",r); + + buf = msg; + for(ii = 0 ; ii < r ; ii+=16) + { + for(jj = 0 ; jj < 16 ; jj+=2 ) + { + log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]); + if((ii+jj) > r) break; + } + log(" : "); + for(jj = 0 ; jj < 16 ; jj+=2 ) + { + log("%c%c",buf[ii+jj],buf[ii+jj+1]); + if((ii+jj) > r) break; + } + log("\r\n"); + if((ii+jj) > r) break; + } +#endif + + r = 0; + + return r; +} + +/** + * Writes an ADB command with a string as payload. + * + * @param device USB device handle. + * @param command ADB command. + * @param arg0 first ADB argument (command dependent). + * @param arg0 second ADB argument (command dependent). + * @param str payload string. + * @return error code or 0 for success. + */ +int ADB::writeStringMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1, char * str) +{ + return ADB::writeMessage(device, command, arg0, arg1, strlen(str) + 1, (uint8_t*)str); +} + +/** + * Poll an ADB message. + * @param message on success, the ADB message will be returned in this struct. + * @param poll true to poll for a packet on the input endpoint, false to wait for a packet. Use false here when a packet is expected (i.e. OKAY in response to WRTE) + * @return true iff a packet was successfully received, false otherwise. + */ +boolean ADB::pollMessage(adb_message * message, boolean poll) +{ + int bytesRead = 0; + uint8_t buf[ADB_USB_PACKETSIZE]; + + // Poll a packet from the USB + bytesRead = recv_packet_buf.GetPacket((char*)buf); + + // Check if the USB in transfer was successful. + if (bytesRead<=0) return false; + + log("[pollMessage] byteRead size:%d\r\n",bytesRead); + + // Check if the buffer contains a valid message + memcpy((void*)message, (void*)buf, sizeof(adb_message)); + + // If the message is corrupt, return. +#if 1 + if (message->magic != (message->command ^ 0xffffffff)) + { +#ifdef DEBUG + printf("Broken message, magic mismatch, %d bytes\r\n", bytesRead); + return false; +#endif + } +#endif + // Check if the received number of bytes matches our expected 24 bytes of ADB message header. + if (bytesRead != sizeof(adb_message)) return false; + + return true; +} + +/** + * Sends an ADB OPEN message for any connections that are currently in the CLOSED state. + */ +void ADB::openClosedConnections() +{ + uint32_t timeSinceLastConnect; + Connection * connection; + + // Iterate over the connection list and send "OPEN" for the ones that are currently closed. + for (connection = firstConnection; connection!=NULL; connection = connection->next) + { + timeSinceLastConnect = millis() - connection->lastConnectionAttempt; + if (connection->status==ADB_CLOSED && timeSinceLastConnect>ADB_CONNECTION_RETRY_TIME) + { + // Issue open command. + ADB::writeStringMessage(_device, A_OPEN, connection->localID, 0, connection->connectionString); + + // Record the last attempt time + connection->lastConnectionAttempt = millis(); + connection->status = ADB_OPENING; + + } + } + +} + +/** + * Handles and ADB OKAY message, which represents a transition in the connection state machine. + * + * @param connection ADB connection + * @param message ADB message struct. + */ +void ADB::handleOkay(Connection * connection, adb_message * message) +{ + // Check if the OKAY message was a response to a CONNECT message. + if (connection->status==ADB_OPENING) + { + connection->status = ADB_OPEN; + connection->remoteID = message->arg0; + + ADB::fireEvent(connection, ADB_CONNECTION_OPEN, 0, NULL); + } + + // Check if the OKAY message was a response to a WRITE message. + if (connection->status == ADB_WRITING) + connection->status = ADB_OPEN; + +} + +/** + * Handles an ADB CLOSE message, and fires an ADB event accordingly. + * + * @param connection ADB connection + */ +void ADB::handleClose(Connection * connection) +{ + // Check if the CLOSE message was a response to a CONNECT message. + if (connection->status==ADB_OPENING) + ADB::fireEvent(connection, ADB_CONNECTION_FAILED, 0, NULL); + else + ADB::fireEvent(connection, ADB_CONNECTION_CLOSE, 0, NULL); + + // Connection failed + if (connection->reconnect) + connection->status = ADB_CLOSED; + else + connection->status = ADB_UNUSED; + +} + +/** + * Handles an ADB WRITE message. + * + * @param connection ADB connection + * @param message ADB message struct. + */ +void ADB::handleWrite(Connection * connection, adb_message * message) +{ + uint32_t bytesLeft = message->data_length; + uint8_t buf[ADB_USB_PACKETSIZE]; + ConnectionStatus previousStatus; + int bytesRead; + + previousStatus = connection->status; + + connection->status = ADB_RECEIVING; + connection->dataRead = 0; + connection->dataSize = message->data_length; + + while (bytesLeft>0) + { + int len = bytesLeft < ADB_USB_PACKETSIZE ? bytesLeft : ADB_USB_PACKETSIZE; + + // Read payload + bytesRead = recv_packet_buf.GetPacket((char*)buf); + + + // Poll the USB layer. + USBLoop(); + + log("[handleWrite] byteRead size:%d\r\n",bytesRead); + +// if (len != bytesRead) +// printf("bytes read mismatch: %d expected, %d read, %ld left\r\n", len, bytesRead, bytesLeft); + + // Break out of the read loop if there's no data to read :( + if (bytesRead==-1) break; + else if(bytesRead!=0) + { + connection->dataRead += len; + ADB::fireEvent(connection, ADB_CONNECTION_RECEIVE, len, buf); + + bytesLeft -= bytesRead; + } + } + + // Send OKAY message in reply. + bytesRead = ADB::writeEmptyMessage(_device, A_OKAY, message->arg1, message->arg0); + + connection->status = previousStatus; + +} + +/** + * Close all ADB connections. + * + * @param connection ADB connection + * @param message ADB message struct. + */ +void ADB::closeAll() +{ + Connection * connection; + + // Iterate over all connections and close the ones that are currently open. + for (connection = firstConnection; connection != NULL; connection = connection->next) + if (!(connection->status==ADB_UNUSED || connection->status==ADB_CLOSED)) + ADB::handleClose(connection); + +} + +/** + * Handles an ADB connect message. This is a response to a connect message sent from our side. + * @param message ADB message. + */ +void ADB::handleConnect(adb_message * message) +{ + unsigned int bytesRead; + uint8_t buf[MAX_BUF_SIZE]; + uint16_t len; + + // Read payload (remote ADB device ID) + len = message->data_length < MAX_BUF_SIZE ? message->data_length : MAX_BUF_SIZE; + bytesRead = recv_packet_buf.GetPacket((char*)buf); + + log("[handleConnect] byteRead size:%d\r\n",bytesRead); + + // Signal that we are now connected to an Android device (yay!) + connected = true; + + // Fire event. + ADB::fireEvent(NULL, ADB_CONNECT, len, buf); + +} + +/** + * This method is called periodically to check for new messages on the USB bus and process them. + */ +void ADB::poll() +{ + Connection * connection; + adb_message message; + + // Poll the USB layer. + USBLoop(); + + // If no USB device, there's no work for us to be done, so just return. + if (_device==0) return; + + // If not connected, send a connection string to the device. + if (!connected) + { + ADB::writeStringMessage(_device, A_CNXN, 0x01000000, 4096, (char*)"host::microbridge"); + for(int ii=0;ii<400;ii++) + { + USBLoop(); + wait_ms(1); + } + //wait_ms(500); // Give the device some time to respond. + } + + // If we are connected, check if there are connections that need to be opened + if (connected) + ADB::openClosedConnections(); + + // Check for an incoming ADB message. + if (!ADB::pollMessage(&message, true)) + return; + + // Handle a response from the ADB device to our CONNECT message. + if (message.command == A_CNXN) + ADB::handleConnect(&message); + + // Handle messages for specific connections + for (connection = firstConnection; connection != NULL; connection = connection->next) + { + if(connection->status!=ADB_UNUSED && connection->localID==message.arg1) + { + switch(message.command) + { + case A_OKAY: + //printf("HANDLE OKEY\r\n"); + ADB::handleOkay(connection, &message); + break; + case A_CLSE: + printf("HANDLE CLOSE\r\n"); + ADB::handleClose(connection); + break; + case A_WRTE: + //printf("HANDLE WRITE\r\n"); + ADB::handleWrite(connection, &message); + break; + default: + break; + } + } + } + +} + +void ADB::AdbreadCallback(int device, int endpoint, int status, u8* buf, int len, void* userData) { + + recv_packet_buf.PutPacket((char*)buf,len); + +#ifdef DEBUG + log("[AdbreadCallback] size:%d\r\n",len); + + int ii,jj; + for(ii = 0 ; ii < len ; ii+=16) + { + for(jj = 0 ; jj < 16 ; jj+=2 ) + { + log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]); + if((ii+jj) > len) break; + } + log(" : "); + for(jj = 0 ; jj < 16 ; jj+=2 ) + { + log("%c%c",buf[ii+jj],buf[ii+jj+1]); + if((ii+jj) > len) break; + } + log("\r\n"); + if((ii+jj) > len) break; + } +#endif + USBBulkTransfer(device, endpoint ,readbuff,sizeof(readbuff), AdbreadCallback, userData); + // wait_ms(4); +} + +/** + * Checks whether the a connected USB device is an ADB device and populates a configuration record if it is. + * + * @param device USB device. + * @param handle pointer to a configuration record. The endpoint device address, configuration, and endpoint information will be stored here. + * @return true iff the device is an ADB device. + */ +boolean ADB::isAdbDevice(int device, int configuration, int interfaceNumber) +{ + boolean ret = false; + + log("connecting Android \r\n"); + + _device = device; + _configuration = configuration; + _interfaceNumber = interfaceNumber; + + log("device = %d configuration = %d interfaceNumber = %d\r\n", device, configuration, interfaceNumber); + + int err; + + u8 buffer[255]; + err = GetDescriptor(_device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,4); + + if (err < 0) { + log("Failed to get descriptor\r\n"); + return(ret); + } + + int len = buffer[2] | (buffer[3] << 8); + if (len > sizeof(buffer)) { + log("config descriptor too large\r\n"); + /* might want to truncate here */ + return(ret); + } + err = GetDescriptor(_device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,len); + u8* p = buffer; + input_ep=0; + output_ep=0; + EndpointDescriptor *epDesc; + + log("Descriptor size:%d\r\n",len); + int ii,jj; + for(ii = 0 ; ii < len ; ii+=16) + { + for(jj = 0 ; jj < 16 ; jj+=2 ) + { + log("%02X%02X ",buffer[ii+jj],buffer[ii+jj+1]); + if((ii+jj) > len) break; + } + log("\r\n"); + if((ii+jj) > len) break; + } + u8 interface_num = 0; + + while (p<(buffer+len)) { + u8 descLen = p[0]; + u8 descType = p[1]; + log("descLen=%d,descType=%d\r\n",descLen,descType); + switch (descType) { + case DESCRIPTOR_TYPE_CONFIGURATION: + log("config desc\r\n"); + break; + case DESCRIPTOR_TYPE_INTERFACE: + interface_num = p[2]; + log("interface desc num[%d]\r\n",interface_num); + break; + case DESCRIPTOR_TYPE_ENDPOINT: + epDesc=(EndpointDescriptor*)p; + if( interface_num == 1 ) + { + if (!input_ep && (epDesc->bEndpointAddress& 0x80)) { + input_ep=epDesc->bEndpointAddress& 0x7f; + //PacketSize drop + log("input Endpoint address=%d,wMaxPacketSize=%d,bmAttributes=%d\r\n",input_ep,epDesc->wMaxPacketSize,epDesc->bmAttributes); + + } else if (!output_ep) { + output_ep=epDesc->bEndpointAddress& 0x7f; + //PacketSize drop + log("output Endpoint address=%d,wMaxPacketSize=%d,bmAttributes=%d\r\n",output_ep,epDesc->wMaxPacketSize,epDesc->bmAttributes); + } else { + //other + log("non input,output Endpoint address=%d,wMaxPacketSize=%d,bmAttributes=%d\r\n",input_ep,epDesc->wMaxPacketSize,epDesc->bmAttributes); + } + } + break; + default: + log("unkown desc type(%d) \r\n",descType); + } + p+=descLen; + } + + if (!(input_ep && output_ep)) { + log("can't find accessory endpoints\r\n"); + return(false); + } + + log("SetConfiguration\r\n"); + err = SetConfiguration(device,configuration); + if (err < 0) { + log("SetConfiguration error\r\n"); + return(false); + } + + log("interrupt setup\r\n"); + //interrupt setup + if (IO_PENDING!=USBBulkTransfer(_device,input_ep|0x80,readbuff,sizeof(readbuff),AdbreadCallback,NULL)) return(ret); + + log("ADB Standby\r\n"); + ret = true; + + return(ret); +} + + +void desconnect(void) +{ + ADB::closeAll(); + _device = 0; + connected = false; +} + +/** + * Write a set of bytes to an open ADB connection. + * + * @param connection ADB connection to write the data to. + * @param length number of bytes to transmit. + * @param data data to send. + * @return number of transmitted bytes, or -1 on failure. + */ +int ADB::write(Connection * connection, uint16_t length, uint8_t * data) +{ + int ret; + + // First check if we have a working ADB connection + if (_device==0 || !connected) return -1; + + // Check if the connection is open for writing. + if (connection->status != ADB_OPEN) return -2; + + // Write payload + ret = ADB::writeMessage(_device, A_WRTE, connection->localID, connection->remoteID, length, data); + if (ret==0) + connection->status = ADB_WRITING; + + return ret; +} + +/** + * Write a string to an open ADB connection. The trailing zero is not transmitted. + * + * @param connection ADB connection to write the data to. + * @param length number of bytes to transmit. + * @param data data to send. + * @return number of transmitted bytes, or -1 on failure. + */ +int ADB::writeString(Connection * connection, char * str) +{ + int ret; + + // First check if we have a working ADB connection + if (_device==0 || !connected) return -1; + + // Check if the connection is open for writing. + if (connection->status != ADB_OPEN) return -2; + + // Write payload + ret = ADB::writeStringMessage(_device, A_WRTE, connection->localID, connection->remoteID, str); + if (ret==0) + connection->status = ADB_WRITING; + + return ret; +} + +/** + * Write a set of bytes to this ADB connection. + * + * @param length number of bytes to transmit. + * @param data data to send. + * @return number of transmitted bytes, or -1 on failure. + */ +int Connection::write(uint16_t length, uint8_t * data) +{ + return ADB::write(this, length, data); +} + +/** + * Write a string to this connection. + * + * @param length number of bytes to transmit. + * @param data data to send. + * @return number of transmitted bytes, or -1 on failure. + */ +int Connection::writeString(char * str) +{ + return ADB::writeString(this, str); +} + +/** + * Checks if the connection is open for writing. + * @return true iff the connection is open and ready to accept write commands. + */ +bool Connection::isOpen() +{ + return this->status == ADB_OPEN; +} + + +/** from USBHost load function. initialize Android device**/ +void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc) { + char s[128]; + + log("LoadDevice %d %02X:%02X:%02X\r\n",device,interfaceDesc->bInterfaceClass,interfaceDesc->bInterfaceSubClass,interfaceDesc->bInterfaceProtocol); + + for (int i = 1; i < 4; i++) { + if (GetString(device,i,s,sizeof(s)) < 0) + break; + printf("%d: %s\r\n",i,s); + } + + // Adb? + if(1) + { + ADB::isAdbDevice(device,1,2); + } + +}