This program is for an autonomous robot for the competition at the Hochschule Luzern. We are one of the 32 teams. <a href="http://cruisingcrepe.wordpress.com/">http://cruisingcrepe.wordpress.com/</a> 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: <a href="http://www.dis.uniroma1.it/~labrob/pub/papers/Ramsete01.pdf">http://www.dis.uniroma1.it/~labrob/pub/papers/Ramsete01.pdf</a>

Dependencies:   mbed

Fork of autonomousRobotAndroid by Christian Burri

Committer:
chrigelburri
Date:
Fri May 03 06:30:46 2013 +0000
Revision:
17:f0a973f17917
bastel mit adb

Who changed what in which revision?

UserRevisionLine numberNew contents of line
chrigelburri 17:f0a973f17917 1 /*
chrigelburri 17:f0a973f17917 2 Copyright 2011 Niels Brouwers
chrigelburri 17:f0a973f17917 3
chrigelburri 17:f0a973f17917 4 Licensed under the Apache License, Version 2.0 (the "License");
chrigelburri 17:f0a973f17917 5 you may not use this file except in compliance with the License.
chrigelburri 17:f0a973f17917 6 You may obtain a copy of the License at
chrigelburri 17:f0a973f17917 7
chrigelburri 17:f0a973f17917 8 http://www.apache.org/licenses/LICENSE-2.0
chrigelburri 17:f0a973f17917 9
chrigelburri 17:f0a973f17917 10 Unless required by applicable law or agreed to in writing, software
chrigelburri 17:f0a973f17917 11 distributed under the License is distributed on an "AS IS" BASIS,
chrigelburri 17:f0a973f17917 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
chrigelburri 17:f0a973f17917 13 See the License for the specific language governing permissions and
chrigelburri 17:f0a973f17917 14 limitations under the License.
chrigelburri 17:f0a973f17917 15 */
chrigelburri 17:f0a973f17917 16
chrigelburri 17:f0a973f17917 17 /* Changed by Junichi Katsu */
chrigelburri 17:f0a973f17917 18
chrigelburri 17:f0a973f17917 19 #include <string.h>
chrigelburri 17:f0a973f17917 20 #include <Adb.h>
chrigelburri 17:f0a973f17917 21
chrigelburri 17:f0a973f17917 22 //#define DEBUG
chrigelburri 17:f0a973f17917 23
chrigelburri 17:f0a973f17917 24 #define MAX_BUF_SIZE 128
chrigelburri 17:f0a973f17917 25
chrigelburri 17:f0a973f17917 26 #ifdef DEBUG
chrigelburri 17:f0a973f17917 27 #define log(...) printf(__VA_ARGS__)
chrigelburri 17:f0a973f17917 28 #else
chrigelburri 17:f0a973f17917 29 #define log(...) do {} while(0)
chrigelburri 17:f0a973f17917 30 #endif
chrigelburri 17:f0a973f17917 31
chrigelburri 17:f0a973f17917 32 int input_ep;
chrigelburri 17:f0a973f17917 33 int output_ep;
chrigelburri 17:f0a973f17917 34 int _device;
chrigelburri 17:f0a973f17917 35 int _configuration;
chrigelburri 17:f0a973f17917 36 int _interfaceNumber;
chrigelburri 17:f0a973f17917 37
chrigelburri 17:f0a973f17917 38 static Connection * firstConnection;
chrigelburri 17:f0a973f17917 39 static boolean connected;
chrigelburri 17:f0a973f17917 40 static int connectionLocalId = 1;
chrigelburri 17:f0a973f17917 41 unsigned char readbuff[MAX_BUF_SIZE];
chrigelburri 17:f0a973f17917 42
chrigelburri 17:f0a973f17917 43 // Event handler callback function.
chrigelburri 17:f0a973f17917 44 adb_eventHandler * eventHandler;
chrigelburri 17:f0a973f17917 45
chrigelburri 17:f0a973f17917 46 ADB* _adb;
chrigelburri 17:f0a973f17917 47 PacketBuffer recv_packet_buf(100,MAX_BUF_SIZE);
chrigelburri 17:f0a973f17917 48 Ticker timer;
chrigelburri 17:f0a973f17917 49
chrigelburri 17:f0a973f17917 50 int time_ms = 0;
chrigelburri 17:f0a973f17917 51
chrigelburri 17:f0a973f17917 52
chrigelburri 17:f0a973f17917 53 void attime(void)
chrigelburri 17:f0a973f17917 54 {
chrigelburri 17:f0a973f17917 55 time_ms++;
chrigelburri 17:f0a973f17917 56 }
chrigelburri 17:f0a973f17917 57
chrigelburri 17:f0a973f17917 58 int millis()
chrigelburri 17:f0a973f17917 59 {
chrigelburri 17:f0a973f17917 60 return(time_ms);
chrigelburri 17:f0a973f17917 61 }
chrigelburri 17:f0a973f17917 62
chrigelburri 17:f0a973f17917 63 char *strdup(const char *src)
chrigelburri 17:f0a973f17917 64 {
chrigelburri 17:f0a973f17917 65 char *p;
chrigelburri 17:f0a973f17917 66
chrigelburri 17:f0a973f17917 67 if(src == NULL){
chrigelburri 17:f0a973f17917 68 return NULL;
chrigelburri 17:f0a973f17917 69 }
chrigelburri 17:f0a973f17917 70
chrigelburri 17:f0a973f17917 71 p = (char *)malloc(strlen(src) + 1);
chrigelburri 17:f0a973f17917 72 if(p != NULL) strcpy(p, src);
chrigelburri 17:f0a973f17917 73 return p;
chrigelburri 17:f0a973f17917 74
chrigelburri 17:f0a973f17917 75 }
chrigelburri 17:f0a973f17917 76
chrigelburri 17:f0a973f17917 77 /**
chrigelburri 17:f0a973f17917 78 * Initialises the ADB protocol. This function initialises the USB layer underneath so no further setup is required.
chrigelburri 17:f0a973f17917 79 */
chrigelburri 17:f0a973f17917 80 void ADB::init()
chrigelburri 17:f0a973f17917 81 {
chrigelburri 17:f0a973f17917 82 recv_packet_buf.clear();
chrigelburri 17:f0a973f17917 83
chrigelburri 17:f0a973f17917 84 // Signal that we are not connected.
chrigelburri 17:f0a973f17917 85 _device = 0;
chrigelburri 17:f0a973f17917 86 connected = false;
chrigelburri 17:f0a973f17917 87
chrigelburri 17:f0a973f17917 88
chrigelburri 17:f0a973f17917 89 // Initialise Usb host.
chrigelburri 17:f0a973f17917 90 USBInit();
chrigelburri 17:f0a973f17917 91
chrigelburri 17:f0a973f17917 92 timer.attach_us(&attime, 1000);
chrigelburri 17:f0a973f17917 93 }
chrigelburri 17:f0a973f17917 94
chrigelburri 17:f0a973f17917 95 /**
chrigelburri 17:f0a973f17917 96 * Sets the ADB event handler function. This function will be called by the ADB layer
chrigelburri 17:f0a973f17917 97 * when interesting events occur, such as ADB connect/disconnect, connection open/close, and
chrigelburri 17:f0a973f17917 98 * connection writes from the ADB device.
chrigelburri 17:f0a973f17917 99 *
chrigelburri 17:f0a973f17917 100 * @param handler event handler function.
chrigelburri 17:f0a973f17917 101 */
chrigelburri 17:f0a973f17917 102 void ADB::setEventHandler(adb_eventHandler * handler)
chrigelburri 17:f0a973f17917 103 {
chrigelburri 17:f0a973f17917 104 eventHandler = handler;
chrigelburri 17:f0a973f17917 105 }
chrigelburri 17:f0a973f17917 106
chrigelburri 17:f0a973f17917 107 /**
chrigelburri 17:f0a973f17917 108 * Fires an ADB event.
chrigelburri 17:f0a973f17917 109 * @param connection ADB connection. May be NULL in case of global connect/disconnect events.
chrigelburri 17:f0a973f17917 110 * @param type event type.
chrigelburri 17:f0a973f17917 111 * @param length payload length or zero if no payload.
chrigelburri 17:f0a973f17917 112 * @param data payload data if relevant or NULL otherwise.
chrigelburri 17:f0a973f17917 113 */
chrigelburri 17:f0a973f17917 114 void ADB::fireEvent(Connection * connection, adb_eventType type, uint16_t length, uint8_t * data)
chrigelburri 17:f0a973f17917 115 {
chrigelburri 17:f0a973f17917 116 // Fire the global event handler, if set.
chrigelburri 17:f0a973f17917 117 if (eventHandler!=NULL)
chrigelburri 17:f0a973f17917 118 eventHandler(connection, type, length, data);
chrigelburri 17:f0a973f17917 119
chrigelburri 17:f0a973f17917 120 // Fire the event handler of the connection in question, if relevant
chrigelburri 17:f0a973f17917 121 if (connection!=NULL && connection->eventHandler!=NULL)
chrigelburri 17:f0a973f17917 122 connection->eventHandler(connection, type, length, data);
chrigelburri 17:f0a973f17917 123 }
chrigelburri 17:f0a973f17917 124
chrigelburri 17:f0a973f17917 125 /**
chrigelburri 17:f0a973f17917 126 * Adds a new ADB connection. The connection string is per ADB specs, for example "tcp:1234" opens a
chrigelburri 17:f0a973f17917 127 * connection to tcp port 1234, and "shell:ls" outputs a listing of the phone root filesystem. Connections
chrigelburri 17:f0a973f17917 128 * can be made persistent by setting reconnect to true. Persistent connections will be automatically
chrigelburri 17:f0a973f17917 129 * reconnected when the USB cable is re-plugged in. Non-persistent connections will connect only once,
chrigelburri 17:f0a973f17917 130 * and should never be used after they are closed.
chrigelburri 17:f0a973f17917 131 *
chrigelburri 17:f0a973f17917 132 * The connection string is copied into the Connection record and may not exceed ADB_CONNECTIONSTRING_LENGTH-1
chrigelburri 17:f0a973f17917 133 * characters.
chrigelburri 17:f0a973f17917 134 *
chrigelburri 17:f0a973f17917 135 * @param connectionString ADB connectionstring. I.e. "tcp:1234" or "shell:ls".
chrigelburri 17:f0a973f17917 136 * @param reconnect true for automatic reconnect (persistent connections).
chrigelburri 17:f0a973f17917 137 * @param handler event handler.
chrigelburri 17:f0a973f17917 138 * @return an ADB connection record or NULL on failure (not enough slots or connection string too long).
chrigelburri 17:f0a973f17917 139 */
chrigelburri 17:f0a973f17917 140 Connection * ADB::addConnection(const char * connectionString, boolean reconnect, adb_eventHandler * handler)
chrigelburri 17:f0a973f17917 141 {
chrigelburri 17:f0a973f17917 142
chrigelburri 17:f0a973f17917 143 // Allocate a new ADB connection object
chrigelburri 17:f0a973f17917 144 Connection * connection = (Connection*)malloc(sizeof(Connection));
chrigelburri 17:f0a973f17917 145 if (connection == NULL) return NULL;
chrigelburri 17:f0a973f17917 146
chrigelburri 17:f0a973f17917 147 // Allocate memory for the connection string
chrigelburri 17:f0a973f17917 148 connection->connectionString = (char*)strdup(connectionString);
chrigelburri 17:f0a973f17917 149 if (connection->connectionString==NULL)
chrigelburri 17:f0a973f17917 150 {
chrigelburri 17:f0a973f17917 151 // Free the connection object and return null
chrigelburri 17:f0a973f17917 152 free(connection);
chrigelburri 17:f0a973f17917 153 return NULL;
chrigelburri 17:f0a973f17917 154 }
chrigelburri 17:f0a973f17917 155
chrigelburri 17:f0a973f17917 156 // Initialise the newly created object.
chrigelburri 17:f0a973f17917 157 connection->localID = connectionLocalId ++;
chrigelburri 17:f0a973f17917 158 connection->status = ADB_CLOSED;
chrigelburri 17:f0a973f17917 159 connection->lastConnectionAttempt = 0;
chrigelburri 17:f0a973f17917 160 connection->reconnect = reconnect;
chrigelburri 17:f0a973f17917 161 connection->eventHandler = handler;
chrigelburri 17:f0a973f17917 162
chrigelburri 17:f0a973f17917 163 // Add the connection to the linked list. Note that it's easier to just insert
chrigelburri 17:f0a973f17917 164 // at position 0 because you don't have to traverse the list :)
chrigelburri 17:f0a973f17917 165 connection->next = firstConnection;
chrigelburri 17:f0a973f17917 166 firstConnection = connection;
chrigelburri 17:f0a973f17917 167
chrigelburri 17:f0a973f17917 168 // Unable to find an empty spot, all connection slots in use.
chrigelburri 17:f0a973f17917 169 return connection;
chrigelburri 17:f0a973f17917 170 }
chrigelburri 17:f0a973f17917 171
chrigelburri 17:f0a973f17917 172 /**
chrigelburri 17:f0a973f17917 173 * Prints an ADB_message, for debugging purposes.
chrigelburri 17:f0a973f17917 174 * @param message ADB message to print.
chrigelburri 17:f0a973f17917 175 */
chrigelburri 17:f0a973f17917 176 #ifdef DEBUG
chrigelburri 17:f0a973f17917 177 static void adb_printMessage(adb_message * message)
chrigelburri 17:f0a973f17917 178 {
chrigelburri 17:f0a973f17917 179 switch(message->command)
chrigelburri 17:f0a973f17917 180 {
chrigelburri 17:f0a973f17917 181 case A_OKAY:
chrigelburri 17:f0a973f17917 182 printf("OKAY message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
chrigelburri 17:f0a973f17917 183 break;
chrigelburri 17:f0a973f17917 184 case A_CLSE:
chrigelburri 17:f0a973f17917 185 printf("CLSE message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
chrigelburri 17:f0a973f17917 186 break;
chrigelburri 17:f0a973f17917 187 case A_WRTE:
chrigelburri 17:f0a973f17917 188 printf("WRTE message [%lx] %ld %ld, %ld bytes\r\n", message->command, message->arg0, message->arg1, message->data_length);
chrigelburri 17:f0a973f17917 189 break;
chrigelburri 17:f0a973f17917 190 case A_CNXN:
chrigelburri 17:f0a973f17917 191 printf("CNXN message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
chrigelburri 17:f0a973f17917 192 break;
chrigelburri 17:f0a973f17917 193 case A_SYNC:
chrigelburri 17:f0a973f17917 194 printf("SYNC message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
chrigelburri 17:f0a973f17917 195 break;
chrigelburri 17:f0a973f17917 196 case A_OPEN:
chrigelburri 17:f0a973f17917 197 printf("OPEN message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
chrigelburri 17:f0a973f17917 198 break;
chrigelburri 17:f0a973f17917 199 default:
chrigelburri 17:f0a973f17917 200 printf("WTF message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
chrigelburri 17:f0a973f17917 201 break;
chrigelburri 17:f0a973f17917 202 }
chrigelburri 17:f0a973f17917 203 }
chrigelburri 17:f0a973f17917 204 #endif
chrigelburri 17:f0a973f17917 205
chrigelburri 17:f0a973f17917 206 /**
chrigelburri 17:f0a973f17917 207 * Writes an empty message (without payload) to the ADB device.
chrigelburri 17:f0a973f17917 208 *
chrigelburri 17:f0a973f17917 209 * @param device USB device handle.
chrigelburri 17:f0a973f17917 210 * @param command ADB command.
chrigelburri 17:f0a973f17917 211 * @param arg0 first ADB argument (command dependent).
chrigelburri 17:f0a973f17917 212 * @param arg0 second ADB argument (command dependent).
chrigelburri 17:f0a973f17917 213 * @return error code or 0 for success.
chrigelburri 17:f0a973f17917 214 */
chrigelburri 17:f0a973f17917 215 int ADB::writeEmptyMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1)
chrigelburri 17:f0a973f17917 216 {
chrigelburri 17:f0a973f17917 217 adb_message message;
chrigelburri 17:f0a973f17917 218
chrigelburri 17:f0a973f17917 219 message.command = command;
chrigelburri 17:f0a973f17917 220 message.arg0 = arg0;
chrigelburri 17:f0a973f17917 221 message.arg1 = arg1;
chrigelburri 17:f0a973f17917 222 message.data_length = 0;
chrigelburri 17:f0a973f17917 223 message.data_check = 0;
chrigelburri 17:f0a973f17917 224 message.magic = command ^ 0xffffffff;
chrigelburri 17:f0a973f17917 225
chrigelburri 17:f0a973f17917 226 #ifdef DEBUG
chrigelburri 17:f0a973f17917 227 printf("OUT << "); adb_printMessage(&message);
chrigelburri 17:f0a973f17917 228 #endif
chrigelburri 17:f0a973f17917 229
chrigelburri 17:f0a973f17917 230 int r = USBBulkTransfer( device , output_ep , (uint8_t*)&message , sizeof(adb_message) );
chrigelburri 17:f0a973f17917 231
chrigelburri 17:f0a973f17917 232 #ifdef DEBUG
chrigelburri 17:f0a973f17917 233 log("[writeMessage1] size:%d\r\n",r);
chrigelburri 17:f0a973f17917 234
chrigelburri 17:f0a973f17917 235 int ii,jj;
chrigelburri 17:f0a973f17917 236 uint8_t* buf = (uint8_t*)&message;
chrigelburri 17:f0a973f17917 237 for(ii = 0 ; ii < r ; ii+=16)
chrigelburri 17:f0a973f17917 238 {
chrigelburri 17:f0a973f17917 239 for(jj = 0 ; jj < 16 ; jj+=2 )
chrigelburri 17:f0a973f17917 240 {
chrigelburri 17:f0a973f17917 241 log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]);
chrigelburri 17:f0a973f17917 242 if((ii+jj) > r) break;
chrigelburri 17:f0a973f17917 243 }
chrigelburri 17:f0a973f17917 244 log(" : ");
chrigelburri 17:f0a973f17917 245 for(jj = 0 ; jj < 16 ; jj+=2 )
chrigelburri 17:f0a973f17917 246 {
chrigelburri 17:f0a973f17917 247 log("%c%c",buf[ii+jj],buf[ii+jj+1]);
chrigelburri 17:f0a973f17917 248 if((ii+jj) > r) break;
chrigelburri 17:f0a973f17917 249 }
chrigelburri 17:f0a973f17917 250 log("\r\n");
chrigelburri 17:f0a973f17917 251 if((ii+jj) > r) break;
chrigelburri 17:f0a973f17917 252 }
chrigelburri 17:f0a973f17917 253 #endif
chrigelburri 17:f0a973f17917 254
chrigelburri 17:f0a973f17917 255 return r;
chrigelburri 17:f0a973f17917 256 }
chrigelburri 17:f0a973f17917 257
chrigelburri 17:f0a973f17917 258 /**
chrigelburri 17:f0a973f17917 259 * Writes an ADB message with payload to the ADB device.
chrigelburri 17:f0a973f17917 260 *
chrigelburri 17:f0a973f17917 261 * @param device USB device handle.
chrigelburri 17:f0a973f17917 262 * @param command ADB command.
chrigelburri 17:f0a973f17917 263 * @param arg0 first ADB argument (command dependent).
chrigelburri 17:f0a973f17917 264 * @param arg0 second ADB argument (command dependent).
chrigelburri 17:f0a973f17917 265 * @param length payload length.
chrigelburri 17:f0a973f17917 266 * @param data command payload.
chrigelburri 17:f0a973f17917 267 * @return error code or 0 for success.
chrigelburri 17:f0a973f17917 268 */
chrigelburri 17:f0a973f17917 269 int ADB::writeMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1, uint32_t length, uint8_t * data)
chrigelburri 17:f0a973f17917 270 {
chrigelburri 17:f0a973f17917 271 adb_message message;
chrigelburri 17:f0a973f17917 272 uint8_t msg[256];
chrigelburri 17:f0a973f17917 273 uint32_t count, sum = 0;
chrigelburri 17:f0a973f17917 274 uint8_t * x;
chrigelburri 17:f0a973f17917 275
chrigelburri 17:f0a973f17917 276 // Calculate data checksum
chrigelburri 17:f0a973f17917 277 count = length;
chrigelburri 17:f0a973f17917 278 x = data;
chrigelburri 17:f0a973f17917 279 while(count-- > 0) sum += *x++;
chrigelburri 17:f0a973f17917 280
chrigelburri 17:f0a973f17917 281 // Fill out the message record.
chrigelburri 17:f0a973f17917 282 message.command = command;
chrigelburri 17:f0a973f17917 283 message.arg0 = arg0;
chrigelburri 17:f0a973f17917 284 message.arg1 = arg1;
chrigelburri 17:f0a973f17917 285 message.data_length = length;
chrigelburri 17:f0a973f17917 286 message.data_check = (sum);
chrigelburri 17:f0a973f17917 287 message.magic = command ^ 0xffffffff;
chrigelburri 17:f0a973f17917 288
chrigelburri 17:f0a973f17917 289 #ifdef DEBUG
chrigelburri 17:f0a973f17917 290 printf("OUT << "); adb_printMessage(&message);
chrigelburri 17:f0a973f17917 291 #endif
chrigelburri 17:f0a973f17917 292
chrigelburri 17:f0a973f17917 293 int r = USBBulkTransfer( device , output_ep , (uint8_t*)&message , sizeof(adb_message) );
chrigelburri 17:f0a973f17917 294
chrigelburri 17:f0a973f17917 295 if (r<0) return r;
chrigelburri 17:f0a973f17917 296
chrigelburri 17:f0a973f17917 297 #ifdef DEBUG
chrigelburri 17:f0a973f17917 298 log("[writeMessage1] size:%d\r\n",r);
chrigelburri 17:f0a973f17917 299
chrigelburri 17:f0a973f17917 300 int ii,jj;
chrigelburri 17:f0a973f17917 301 uint8_t* buf = (uint8_t*)&message;
chrigelburri 17:f0a973f17917 302 for(ii = 0 ; ii < r ; ii+=16)
chrigelburri 17:f0a973f17917 303 {
chrigelburri 17:f0a973f17917 304 for(jj = 0 ; jj < 16 ; jj+=2 )
chrigelburri 17:f0a973f17917 305 {
chrigelburri 17:f0a973f17917 306 log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]);
chrigelburri 17:f0a973f17917 307 if((ii+jj) > r) break;
chrigelburri 17:f0a973f17917 308 }
chrigelburri 17:f0a973f17917 309 log(" : ");
chrigelburri 17:f0a973f17917 310 for(jj = 0 ; jj < 16 ; jj+=2 )
chrigelburri 17:f0a973f17917 311 {
chrigelburri 17:f0a973f17917 312 log("%c%c",buf[ii+jj],buf[ii+jj+1]);
chrigelburri 17:f0a973f17917 313 if((ii+jj) > r) break;
chrigelburri 17:f0a973f17917 314 }
chrigelburri 17:f0a973f17917 315 log("\r\n");
chrigelburri 17:f0a973f17917 316 if((ii+jj) > r) break;
chrigelburri 17:f0a973f17917 317 }
chrigelburri 17:f0a973f17917 318 #endif
chrigelburri 17:f0a973f17917 319
chrigelburri 17:f0a973f17917 320 memcpy( msg , data , length );
chrigelburri 17:f0a973f17917 321
chrigelburri 17:f0a973f17917 322 r = USBBulkTransfer( device , output_ep , msg , length );
chrigelburri 17:f0a973f17917 323 log("USB SEND RET2:%d\r\n",r);
chrigelburri 17:f0a973f17917 324
chrigelburri 17:f0a973f17917 325 if (r<0) return r;
chrigelburri 17:f0a973f17917 326
chrigelburri 17:f0a973f17917 327 #ifdef DEBUG
chrigelburri 17:f0a973f17917 328 log("[writeMessage2] size:%d\r\n",r);
chrigelburri 17:f0a973f17917 329
chrigelburri 17:f0a973f17917 330 buf = msg;
chrigelburri 17:f0a973f17917 331 for(ii = 0 ; ii < r ; ii+=16)
chrigelburri 17:f0a973f17917 332 {
chrigelburri 17:f0a973f17917 333 for(jj = 0 ; jj < 16 ; jj+=2 )
chrigelburri 17:f0a973f17917 334 {
chrigelburri 17:f0a973f17917 335 log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]);
chrigelburri 17:f0a973f17917 336 if((ii+jj) > r) break;
chrigelburri 17:f0a973f17917 337 }
chrigelburri 17:f0a973f17917 338 log(" : ");
chrigelburri 17:f0a973f17917 339 for(jj = 0 ; jj < 16 ; jj+=2 )
chrigelburri 17:f0a973f17917 340 {
chrigelburri 17:f0a973f17917 341 log("%c%c",buf[ii+jj],buf[ii+jj+1]);
chrigelburri 17:f0a973f17917 342 if((ii+jj) > r) break;
chrigelburri 17:f0a973f17917 343 }
chrigelburri 17:f0a973f17917 344 log("\r\n");
chrigelburri 17:f0a973f17917 345 if((ii+jj) > r) break;
chrigelburri 17:f0a973f17917 346 }
chrigelburri 17:f0a973f17917 347 #endif
chrigelburri 17:f0a973f17917 348
chrigelburri 17:f0a973f17917 349 r = 0;
chrigelburri 17:f0a973f17917 350
chrigelburri 17:f0a973f17917 351 return r;
chrigelburri 17:f0a973f17917 352 }
chrigelburri 17:f0a973f17917 353
chrigelburri 17:f0a973f17917 354 /**
chrigelburri 17:f0a973f17917 355 * Writes an ADB command with a string as payload.
chrigelburri 17:f0a973f17917 356 *
chrigelburri 17:f0a973f17917 357 * @param device USB device handle.
chrigelburri 17:f0a973f17917 358 * @param command ADB command.
chrigelburri 17:f0a973f17917 359 * @param arg0 first ADB argument (command dependent).
chrigelburri 17:f0a973f17917 360 * @param arg0 second ADB argument (command dependent).
chrigelburri 17:f0a973f17917 361 * @param str payload string.
chrigelburri 17:f0a973f17917 362 * @return error code or 0 for success.
chrigelburri 17:f0a973f17917 363 */
chrigelburri 17:f0a973f17917 364 int ADB::writeStringMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1, char * str)
chrigelburri 17:f0a973f17917 365 {
chrigelburri 17:f0a973f17917 366 return ADB::writeMessage(device, command, arg0, arg1, strlen(str) + 1, (uint8_t*)str);
chrigelburri 17:f0a973f17917 367 }
chrigelburri 17:f0a973f17917 368
chrigelburri 17:f0a973f17917 369 /**
chrigelburri 17:f0a973f17917 370 * Poll an ADB message.
chrigelburri 17:f0a973f17917 371 * @param message on success, the ADB message will be returned in this struct.
chrigelburri 17:f0a973f17917 372 * @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)
chrigelburri 17:f0a973f17917 373 * @return true iff a packet was successfully received, false otherwise.
chrigelburri 17:f0a973f17917 374 */
chrigelburri 17:f0a973f17917 375 boolean ADB::pollMessage(adb_message * message, boolean poll)
chrigelburri 17:f0a973f17917 376 {
chrigelburri 17:f0a973f17917 377 int bytesRead = 0;
chrigelburri 17:f0a973f17917 378 uint8_t buf[ADB_USB_PACKETSIZE];
chrigelburri 17:f0a973f17917 379
chrigelburri 17:f0a973f17917 380 // Poll a packet from the USB
chrigelburri 17:f0a973f17917 381 bytesRead = recv_packet_buf.GetPacket((char*)buf);
chrigelburri 17:f0a973f17917 382
chrigelburri 17:f0a973f17917 383 // Check if the USB in transfer was successful.
chrigelburri 17:f0a973f17917 384 if (bytesRead<=0) return false;
chrigelburri 17:f0a973f17917 385
chrigelburri 17:f0a973f17917 386 log("[pollMessage] byteRead size:%d\r\n",bytesRead);
chrigelburri 17:f0a973f17917 387
chrigelburri 17:f0a973f17917 388 // Check if the buffer contains a valid message
chrigelburri 17:f0a973f17917 389 memcpy((void*)message, (void*)buf, sizeof(adb_message));
chrigelburri 17:f0a973f17917 390
chrigelburri 17:f0a973f17917 391 // If the message is corrupt, return.
chrigelburri 17:f0a973f17917 392 #if 1
chrigelburri 17:f0a973f17917 393 if (message->magic != (message->command ^ 0xffffffff))
chrigelburri 17:f0a973f17917 394 {
chrigelburri 17:f0a973f17917 395 #ifdef DEBUG
chrigelburri 17:f0a973f17917 396 printf("Broken message, magic mismatch, %d bytes\r\n", bytesRead);
chrigelburri 17:f0a973f17917 397 return false;
chrigelburri 17:f0a973f17917 398 #endif
chrigelburri 17:f0a973f17917 399 }
chrigelburri 17:f0a973f17917 400 #endif
chrigelburri 17:f0a973f17917 401 // Check if the received number of bytes matches our expected 24 bytes of ADB message header.
chrigelburri 17:f0a973f17917 402 if (bytesRead != sizeof(adb_message)) return false;
chrigelburri 17:f0a973f17917 403
chrigelburri 17:f0a973f17917 404 return true;
chrigelburri 17:f0a973f17917 405 }
chrigelburri 17:f0a973f17917 406
chrigelburri 17:f0a973f17917 407 /**
chrigelburri 17:f0a973f17917 408 * Sends an ADB OPEN message for any connections that are currently in the CLOSED state.
chrigelburri 17:f0a973f17917 409 */
chrigelburri 17:f0a973f17917 410 void ADB::openClosedConnections()
chrigelburri 17:f0a973f17917 411 {
chrigelburri 17:f0a973f17917 412 uint32_t timeSinceLastConnect;
chrigelburri 17:f0a973f17917 413 Connection * connection;
chrigelburri 17:f0a973f17917 414
chrigelburri 17:f0a973f17917 415 // Iterate over the connection list and send "OPEN" for the ones that are currently closed.
chrigelburri 17:f0a973f17917 416 for (connection = firstConnection; connection!=NULL; connection = connection->next)
chrigelburri 17:f0a973f17917 417 {
chrigelburri 17:f0a973f17917 418 timeSinceLastConnect = millis() - connection->lastConnectionAttempt;
chrigelburri 17:f0a973f17917 419 if (connection->status==ADB_CLOSED && timeSinceLastConnect>ADB_CONNECTION_RETRY_TIME)
chrigelburri 17:f0a973f17917 420 {
chrigelburri 17:f0a973f17917 421 // Issue open command.
chrigelburri 17:f0a973f17917 422 ADB::writeStringMessage(_device, A_OPEN, connection->localID, 0, connection->connectionString);
chrigelburri 17:f0a973f17917 423
chrigelburri 17:f0a973f17917 424 // Record the last attempt time
chrigelburri 17:f0a973f17917 425 connection->lastConnectionAttempt = millis();
chrigelburri 17:f0a973f17917 426 connection->status = ADB_OPENING;
chrigelburri 17:f0a973f17917 427
chrigelburri 17:f0a973f17917 428 }
chrigelburri 17:f0a973f17917 429 }
chrigelburri 17:f0a973f17917 430
chrigelburri 17:f0a973f17917 431 }
chrigelburri 17:f0a973f17917 432
chrigelburri 17:f0a973f17917 433 /**
chrigelburri 17:f0a973f17917 434 * Handles and ADB OKAY message, which represents a transition in the connection state machine.
chrigelburri 17:f0a973f17917 435 *
chrigelburri 17:f0a973f17917 436 * @param connection ADB connection
chrigelburri 17:f0a973f17917 437 * @param message ADB message struct.
chrigelburri 17:f0a973f17917 438 */
chrigelburri 17:f0a973f17917 439 void ADB::handleOkay(Connection * connection, adb_message * message)
chrigelburri 17:f0a973f17917 440 {
chrigelburri 17:f0a973f17917 441 // Check if the OKAY message was a response to a CONNECT message.
chrigelburri 17:f0a973f17917 442 if (connection->status==ADB_OPENING)
chrigelburri 17:f0a973f17917 443 {
chrigelburri 17:f0a973f17917 444 connection->status = ADB_OPEN;
chrigelburri 17:f0a973f17917 445 connection->remoteID = message->arg0;
chrigelburri 17:f0a973f17917 446
chrigelburri 17:f0a973f17917 447 ADB::fireEvent(connection, ADB_CONNECTION_OPEN, 0, NULL);
chrigelburri 17:f0a973f17917 448 }
chrigelburri 17:f0a973f17917 449
chrigelburri 17:f0a973f17917 450 // Check if the OKAY message was a response to a WRITE message.
chrigelburri 17:f0a973f17917 451 if (connection->status == ADB_WRITING)
chrigelburri 17:f0a973f17917 452 connection->status = ADB_OPEN;
chrigelburri 17:f0a973f17917 453
chrigelburri 17:f0a973f17917 454 }
chrigelburri 17:f0a973f17917 455
chrigelburri 17:f0a973f17917 456 /**
chrigelburri 17:f0a973f17917 457 * Handles an ADB CLOSE message, and fires an ADB event accordingly.
chrigelburri 17:f0a973f17917 458 *
chrigelburri 17:f0a973f17917 459 * @param connection ADB connection
chrigelburri 17:f0a973f17917 460 */
chrigelburri 17:f0a973f17917 461 void ADB::handleClose(Connection * connection)
chrigelburri 17:f0a973f17917 462 {
chrigelburri 17:f0a973f17917 463 // Check if the CLOSE message was a response to a CONNECT message.
chrigelburri 17:f0a973f17917 464 if (connection->status==ADB_OPENING)
chrigelburri 17:f0a973f17917 465 ADB::fireEvent(connection, ADB_CONNECTION_FAILED, 0, NULL);
chrigelburri 17:f0a973f17917 466 else
chrigelburri 17:f0a973f17917 467 ADB::fireEvent(connection, ADB_CONNECTION_CLOSE, 0, NULL);
chrigelburri 17:f0a973f17917 468
chrigelburri 17:f0a973f17917 469 // Connection failed
chrigelburri 17:f0a973f17917 470 if (connection->reconnect)
chrigelburri 17:f0a973f17917 471 connection->status = ADB_CLOSED;
chrigelburri 17:f0a973f17917 472 else
chrigelburri 17:f0a973f17917 473 connection->status = ADB_UNUSED;
chrigelburri 17:f0a973f17917 474
chrigelburri 17:f0a973f17917 475 }
chrigelburri 17:f0a973f17917 476
chrigelburri 17:f0a973f17917 477 /**
chrigelburri 17:f0a973f17917 478 * Handles an ADB WRITE message.
chrigelburri 17:f0a973f17917 479 *
chrigelburri 17:f0a973f17917 480 * @param connection ADB connection
chrigelburri 17:f0a973f17917 481 * @param message ADB message struct.
chrigelburri 17:f0a973f17917 482 */
chrigelburri 17:f0a973f17917 483 void ADB::handleWrite(Connection * connection, adb_message * message)
chrigelburri 17:f0a973f17917 484 {
chrigelburri 17:f0a973f17917 485 uint32_t bytesLeft = message->data_length;
chrigelburri 17:f0a973f17917 486 uint8_t buf[ADB_USB_PACKETSIZE];
chrigelburri 17:f0a973f17917 487 ConnectionStatus previousStatus;
chrigelburri 17:f0a973f17917 488 int bytesRead;
chrigelburri 17:f0a973f17917 489
chrigelburri 17:f0a973f17917 490 previousStatus = connection->status;
chrigelburri 17:f0a973f17917 491
chrigelburri 17:f0a973f17917 492 connection->status = ADB_RECEIVING;
chrigelburri 17:f0a973f17917 493 connection->dataRead = 0;
chrigelburri 17:f0a973f17917 494 connection->dataSize = message->data_length;
chrigelburri 17:f0a973f17917 495
chrigelburri 17:f0a973f17917 496 while (bytesLeft>0)
chrigelburri 17:f0a973f17917 497 {
chrigelburri 17:f0a973f17917 498 int len = bytesLeft < ADB_USB_PACKETSIZE ? bytesLeft : ADB_USB_PACKETSIZE;
chrigelburri 17:f0a973f17917 499
chrigelburri 17:f0a973f17917 500 // Read payload
chrigelburri 17:f0a973f17917 501 bytesRead = recv_packet_buf.GetPacket((char*)buf);
chrigelburri 17:f0a973f17917 502
chrigelburri 17:f0a973f17917 503
chrigelburri 17:f0a973f17917 504 // Poll the USB layer.
chrigelburri 17:f0a973f17917 505 USBLoop();
chrigelburri 17:f0a973f17917 506
chrigelburri 17:f0a973f17917 507 log("[handleWrite] byteRead size:%d\r\n",bytesRead);
chrigelburri 17:f0a973f17917 508
chrigelburri 17:f0a973f17917 509 // if (len != bytesRead)
chrigelburri 17:f0a973f17917 510 // printf("bytes read mismatch: %d expected, %d read, %ld left\r\n", len, bytesRead, bytesLeft);
chrigelburri 17:f0a973f17917 511
chrigelburri 17:f0a973f17917 512 // Break out of the read loop if there's no data to read :(
chrigelburri 17:f0a973f17917 513 if (bytesRead==-1) break;
chrigelburri 17:f0a973f17917 514 else if(bytesRead!=0)
chrigelburri 17:f0a973f17917 515 {
chrigelburri 17:f0a973f17917 516 connection->dataRead += len;
chrigelburri 17:f0a973f17917 517 ADB::fireEvent(connection, ADB_CONNECTION_RECEIVE, len, buf);
chrigelburri 17:f0a973f17917 518
chrigelburri 17:f0a973f17917 519 bytesLeft -= bytesRead;
chrigelburri 17:f0a973f17917 520 }
chrigelburri 17:f0a973f17917 521 }
chrigelburri 17:f0a973f17917 522
chrigelburri 17:f0a973f17917 523 // Send OKAY message in reply.
chrigelburri 17:f0a973f17917 524 bytesRead = ADB::writeEmptyMessage(_device, A_OKAY, message->arg1, message->arg0);
chrigelburri 17:f0a973f17917 525
chrigelburri 17:f0a973f17917 526 connection->status = previousStatus;
chrigelburri 17:f0a973f17917 527
chrigelburri 17:f0a973f17917 528 }
chrigelburri 17:f0a973f17917 529
chrigelburri 17:f0a973f17917 530 /**
chrigelburri 17:f0a973f17917 531 * Close all ADB connections.
chrigelburri 17:f0a973f17917 532 *
chrigelburri 17:f0a973f17917 533 * @param connection ADB connection
chrigelburri 17:f0a973f17917 534 * @param message ADB message struct.
chrigelburri 17:f0a973f17917 535 */
chrigelburri 17:f0a973f17917 536 void ADB::closeAll()
chrigelburri 17:f0a973f17917 537 {
chrigelburri 17:f0a973f17917 538 Connection * connection;
chrigelburri 17:f0a973f17917 539
chrigelburri 17:f0a973f17917 540 // Iterate over all connections and close the ones that are currently open.
chrigelburri 17:f0a973f17917 541 for (connection = firstConnection; connection != NULL; connection = connection->next)
chrigelburri 17:f0a973f17917 542 if (!(connection->status==ADB_UNUSED || connection->status==ADB_CLOSED))
chrigelburri 17:f0a973f17917 543 ADB::handleClose(connection);
chrigelburri 17:f0a973f17917 544
chrigelburri 17:f0a973f17917 545 }
chrigelburri 17:f0a973f17917 546
chrigelburri 17:f0a973f17917 547 /**
chrigelburri 17:f0a973f17917 548 * Handles an ADB connect message. This is a response to a connect message sent from our side.
chrigelburri 17:f0a973f17917 549 * @param message ADB message.
chrigelburri 17:f0a973f17917 550 */
chrigelburri 17:f0a973f17917 551 void ADB::handleConnect(adb_message * message)
chrigelburri 17:f0a973f17917 552 {
chrigelburri 17:f0a973f17917 553 unsigned int bytesRead;
chrigelburri 17:f0a973f17917 554 uint8_t buf[MAX_BUF_SIZE];
chrigelburri 17:f0a973f17917 555 uint16_t len;
chrigelburri 17:f0a973f17917 556
chrigelburri 17:f0a973f17917 557 // Read payload (remote ADB device ID)
chrigelburri 17:f0a973f17917 558 len = message->data_length < MAX_BUF_SIZE ? message->data_length : MAX_BUF_SIZE;
chrigelburri 17:f0a973f17917 559 bytesRead = recv_packet_buf.GetPacket((char*)buf);
chrigelburri 17:f0a973f17917 560
chrigelburri 17:f0a973f17917 561 log("[handleConnect] byteRead size:%d\r\n",bytesRead);
chrigelburri 17:f0a973f17917 562
chrigelburri 17:f0a973f17917 563 // Signal that we are now connected to an Android device (yay!)
chrigelburri 17:f0a973f17917 564 connected = true;
chrigelburri 17:f0a973f17917 565
chrigelburri 17:f0a973f17917 566 // Fire event.
chrigelburri 17:f0a973f17917 567 ADB::fireEvent(NULL, ADB_CONNECT, len, buf);
chrigelburri 17:f0a973f17917 568
chrigelburri 17:f0a973f17917 569 }
chrigelburri 17:f0a973f17917 570
chrigelburri 17:f0a973f17917 571 /**
chrigelburri 17:f0a973f17917 572 * This method is called periodically to check for new messages on the USB bus and process them.
chrigelburri 17:f0a973f17917 573 */
chrigelburri 17:f0a973f17917 574 void ADB::poll()
chrigelburri 17:f0a973f17917 575 {
chrigelburri 17:f0a973f17917 576 Connection * connection;
chrigelburri 17:f0a973f17917 577 adb_message message;
chrigelburri 17:f0a973f17917 578
chrigelburri 17:f0a973f17917 579 // Poll the USB layer.
chrigelburri 17:f0a973f17917 580 USBLoop();
chrigelburri 17:f0a973f17917 581
chrigelburri 17:f0a973f17917 582 // If no USB device, there's no work for us to be done, so just return.
chrigelburri 17:f0a973f17917 583 if (_device==0) return;
chrigelburri 17:f0a973f17917 584
chrigelburri 17:f0a973f17917 585 // If not connected, send a connection string to the device.
chrigelburri 17:f0a973f17917 586 if (!connected)
chrigelburri 17:f0a973f17917 587 {
chrigelburri 17:f0a973f17917 588 ADB::writeStringMessage(_device, A_CNXN, 0x01000000, 4096, (char*)"host::microbridge");
chrigelburri 17:f0a973f17917 589 for(int ii=0;ii<400;ii++)
chrigelburri 17:f0a973f17917 590 {
chrigelburri 17:f0a973f17917 591 USBLoop();
chrigelburri 17:f0a973f17917 592 wait_ms(1);
chrigelburri 17:f0a973f17917 593 }
chrigelburri 17:f0a973f17917 594 //wait_ms(500); // Give the device some time to respond.
chrigelburri 17:f0a973f17917 595 }
chrigelburri 17:f0a973f17917 596
chrigelburri 17:f0a973f17917 597 // If we are connected, check if there are connections that need to be opened
chrigelburri 17:f0a973f17917 598 if (connected)
chrigelburri 17:f0a973f17917 599 ADB::openClosedConnections();
chrigelburri 17:f0a973f17917 600
chrigelburri 17:f0a973f17917 601 // Check for an incoming ADB message.
chrigelburri 17:f0a973f17917 602 if (!ADB::pollMessage(&message, true))
chrigelburri 17:f0a973f17917 603 return;
chrigelburri 17:f0a973f17917 604
chrigelburri 17:f0a973f17917 605 // Handle a response from the ADB device to our CONNECT message.
chrigelburri 17:f0a973f17917 606 if (message.command == A_CNXN)
chrigelburri 17:f0a973f17917 607 ADB::handleConnect(&message);
chrigelburri 17:f0a973f17917 608
chrigelburri 17:f0a973f17917 609 // Handle messages for specific connections
chrigelburri 17:f0a973f17917 610 for (connection = firstConnection; connection != NULL; connection = connection->next)
chrigelburri 17:f0a973f17917 611 {
chrigelburri 17:f0a973f17917 612 if(connection->status!=ADB_UNUSED && connection->localID==message.arg1)
chrigelburri 17:f0a973f17917 613 {
chrigelburri 17:f0a973f17917 614 switch(message.command)
chrigelburri 17:f0a973f17917 615 {
chrigelburri 17:f0a973f17917 616 case A_OKAY:
chrigelburri 17:f0a973f17917 617 //printf("HANDLE OKEY\r\n");
chrigelburri 17:f0a973f17917 618 ADB::handleOkay(connection, &message);
chrigelburri 17:f0a973f17917 619 break;
chrigelburri 17:f0a973f17917 620 case A_CLSE:
chrigelburri 17:f0a973f17917 621 printf("HANDLE CLOSE\r\n");
chrigelburri 17:f0a973f17917 622 ADB::handleClose(connection);
chrigelburri 17:f0a973f17917 623 break;
chrigelburri 17:f0a973f17917 624 case A_WRTE:
chrigelburri 17:f0a973f17917 625 //printf("HANDLE WRITE\r\n");
chrigelburri 17:f0a973f17917 626 ADB::handleWrite(connection, &message);
chrigelburri 17:f0a973f17917 627 break;
chrigelburri 17:f0a973f17917 628 default:
chrigelburri 17:f0a973f17917 629 break;
chrigelburri 17:f0a973f17917 630 }
chrigelburri 17:f0a973f17917 631 }
chrigelburri 17:f0a973f17917 632 }
chrigelburri 17:f0a973f17917 633
chrigelburri 17:f0a973f17917 634 }
chrigelburri 17:f0a973f17917 635
chrigelburri 17:f0a973f17917 636 void ADB::AdbreadCallback(int device, int endpoint, int status, u8* buf, int len, void* userData) {
chrigelburri 17:f0a973f17917 637
chrigelburri 17:f0a973f17917 638 recv_packet_buf.PutPacket((char*)buf,len);
chrigelburri 17:f0a973f17917 639
chrigelburri 17:f0a973f17917 640 #ifdef DEBUG
chrigelburri 17:f0a973f17917 641 log("[AdbreadCallback] size:%d\r\n",len);
chrigelburri 17:f0a973f17917 642
chrigelburri 17:f0a973f17917 643 int ii,jj;
chrigelburri 17:f0a973f17917 644 for(ii = 0 ; ii < len ; ii+=16)
chrigelburri 17:f0a973f17917 645 {
chrigelburri 17:f0a973f17917 646 for(jj = 0 ; jj < 16 ; jj+=2 )
chrigelburri 17:f0a973f17917 647 {
chrigelburri 17:f0a973f17917 648 log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]);
chrigelburri 17:f0a973f17917 649 if((ii+jj) > len) break;
chrigelburri 17:f0a973f17917 650 }
chrigelburri 17:f0a973f17917 651 log(" : ");
chrigelburri 17:f0a973f17917 652 for(jj = 0 ; jj < 16 ; jj+=2 )
chrigelburri 17:f0a973f17917 653 {
chrigelburri 17:f0a973f17917 654 log("%c%c",buf[ii+jj],buf[ii+jj+1]);
chrigelburri 17:f0a973f17917 655 if((ii+jj) > len) break;
chrigelburri 17:f0a973f17917 656 }
chrigelburri 17:f0a973f17917 657 log("\r\n");
chrigelburri 17:f0a973f17917 658 if((ii+jj) > len) break;
chrigelburri 17:f0a973f17917 659 }
chrigelburri 17:f0a973f17917 660 #endif
chrigelburri 17:f0a973f17917 661 USBBulkTransfer(device, endpoint ,readbuff,sizeof(readbuff), AdbreadCallback, userData);
chrigelburri 17:f0a973f17917 662 // wait_ms(4);
chrigelburri 17:f0a973f17917 663 }
chrigelburri 17:f0a973f17917 664
chrigelburri 17:f0a973f17917 665 /**
chrigelburri 17:f0a973f17917 666 * Checks whether the a connected USB device is an ADB device and populates a configuration record if it is.
chrigelburri 17:f0a973f17917 667 *
chrigelburri 17:f0a973f17917 668 * @param device USB device.
chrigelburri 17:f0a973f17917 669 * @param handle pointer to a configuration record. The endpoint device address, configuration, and endpoint information will be stored here.
chrigelburri 17:f0a973f17917 670 * @return true iff the device is an ADB device.
chrigelburri 17:f0a973f17917 671 */
chrigelburri 17:f0a973f17917 672 boolean ADB::isAdbDevice(int device, int configuration, int interfaceNumber)
chrigelburri 17:f0a973f17917 673 {
chrigelburri 17:f0a973f17917 674 boolean ret = false;
chrigelburri 17:f0a973f17917 675
chrigelburri 17:f0a973f17917 676 log("connecting Android \r\n");
chrigelburri 17:f0a973f17917 677
chrigelburri 17:f0a973f17917 678 _device = device;
chrigelburri 17:f0a973f17917 679 _configuration = configuration;
chrigelburri 17:f0a973f17917 680 _interfaceNumber = interfaceNumber;
chrigelburri 17:f0a973f17917 681
chrigelburri 17:f0a973f17917 682 log("device = %d configuration = %d interfaceNumber = %d\r\n", device, configuration, interfaceNumber);
chrigelburri 17:f0a973f17917 683
chrigelburri 17:f0a973f17917 684 int err;
chrigelburri 17:f0a973f17917 685
chrigelburri 17:f0a973f17917 686 u8 buffer[255];
chrigelburri 17:f0a973f17917 687 err = GetDescriptor(_device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,4);
chrigelburri 17:f0a973f17917 688
chrigelburri 17:f0a973f17917 689 if (err < 0) {
chrigelburri 17:f0a973f17917 690 log("Failed to get descriptor\r\n");
chrigelburri 17:f0a973f17917 691 return(ret);
chrigelburri 17:f0a973f17917 692 }
chrigelburri 17:f0a973f17917 693
chrigelburri 17:f0a973f17917 694 int len = buffer[2] | (buffer[3] << 8);
chrigelburri 17:f0a973f17917 695 if (len > sizeof(buffer)) {
chrigelburri 17:f0a973f17917 696 log("config descriptor too large\r\n");
chrigelburri 17:f0a973f17917 697 /* might want to truncate here */
chrigelburri 17:f0a973f17917 698 return(ret);
chrigelburri 17:f0a973f17917 699 }
chrigelburri 17:f0a973f17917 700 err = GetDescriptor(_device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,len);
chrigelburri 17:f0a973f17917 701 u8* p = buffer;
chrigelburri 17:f0a973f17917 702 input_ep=0;
chrigelburri 17:f0a973f17917 703 output_ep=0;
chrigelburri 17:f0a973f17917 704 EndpointDescriptor *epDesc;
chrigelburri 17:f0a973f17917 705
chrigelburri 17:f0a973f17917 706 log("Descriptor size:%d\r\n",len);
chrigelburri 17:f0a973f17917 707 int ii,jj;
chrigelburri 17:f0a973f17917 708 for(ii = 0 ; ii < len ; ii+=16)
chrigelburri 17:f0a973f17917 709 {
chrigelburri 17:f0a973f17917 710 for(jj = 0 ; jj < 16 ; jj+=2 )
chrigelburri 17:f0a973f17917 711 {
chrigelburri 17:f0a973f17917 712 log("%02X%02X ",buffer[ii+jj],buffer[ii+jj+1]);
chrigelburri 17:f0a973f17917 713 if((ii+jj) > len) break;
chrigelburri 17:f0a973f17917 714 }
chrigelburri 17:f0a973f17917 715 log("\r\n");
chrigelburri 17:f0a973f17917 716 if((ii+jj) > len) break;
chrigelburri 17:f0a973f17917 717 }
chrigelburri 17:f0a973f17917 718 u8 interface_num = 0;
chrigelburri 17:f0a973f17917 719
chrigelburri 17:f0a973f17917 720 while (p<(buffer+len)) {
chrigelburri 17:f0a973f17917 721 u8 descLen = p[0];
chrigelburri 17:f0a973f17917 722 u8 descType = p[1];
chrigelburri 17:f0a973f17917 723 log("descLen=%d,descType=%d\r\n",descLen,descType);
chrigelburri 17:f0a973f17917 724 switch (descType) {
chrigelburri 17:f0a973f17917 725 case DESCRIPTOR_TYPE_CONFIGURATION:
chrigelburri 17:f0a973f17917 726 log("config desc\r\n");
chrigelburri 17:f0a973f17917 727 break;
chrigelburri 17:f0a973f17917 728 case DESCRIPTOR_TYPE_INTERFACE:
chrigelburri 17:f0a973f17917 729 interface_num = p[2];
chrigelburri 17:f0a973f17917 730 log("interface desc num[%d]\r\n",interface_num);
chrigelburri 17:f0a973f17917 731 break;
chrigelburri 17:f0a973f17917 732 case DESCRIPTOR_TYPE_ENDPOINT:
chrigelburri 17:f0a973f17917 733 epDesc=(EndpointDescriptor*)p;
chrigelburri 17:f0a973f17917 734 if( interface_num == 1 )
chrigelburri 17:f0a973f17917 735 {
chrigelburri 17:f0a973f17917 736 if (!input_ep && (epDesc->bEndpointAddress& 0x80)) {
chrigelburri 17:f0a973f17917 737 input_ep=epDesc->bEndpointAddress& 0x7f;
chrigelburri 17:f0a973f17917 738 //PacketSize drop
chrigelburri 17:f0a973f17917 739 log("input Endpoint address=%d,wMaxPacketSize=%d,bmAttributes=%d\r\n",input_ep,epDesc->wMaxPacketSize,epDesc->bmAttributes);
chrigelburri 17:f0a973f17917 740
chrigelburri 17:f0a973f17917 741 } else if (!output_ep) {
chrigelburri 17:f0a973f17917 742 output_ep=epDesc->bEndpointAddress& 0x7f;
chrigelburri 17:f0a973f17917 743 //PacketSize drop
chrigelburri 17:f0a973f17917 744 log("output Endpoint address=%d,wMaxPacketSize=%d,bmAttributes=%d\r\n",output_ep,epDesc->wMaxPacketSize,epDesc->bmAttributes);
chrigelburri 17:f0a973f17917 745 } else {
chrigelburri 17:f0a973f17917 746 //other
chrigelburri 17:f0a973f17917 747 log("non input,output Endpoint address=%d,wMaxPacketSize=%d,bmAttributes=%d\r\n",input_ep,epDesc->wMaxPacketSize,epDesc->bmAttributes);
chrigelburri 17:f0a973f17917 748 }
chrigelburri 17:f0a973f17917 749 }
chrigelburri 17:f0a973f17917 750 break;
chrigelburri 17:f0a973f17917 751 default:
chrigelburri 17:f0a973f17917 752 log("unkown desc type(%d) \r\n",descType);
chrigelburri 17:f0a973f17917 753 }
chrigelburri 17:f0a973f17917 754 p+=descLen;
chrigelburri 17:f0a973f17917 755 }
chrigelburri 17:f0a973f17917 756
chrigelburri 17:f0a973f17917 757 if (!(input_ep && output_ep)) {
chrigelburri 17:f0a973f17917 758 log("can't find accessory endpoints\r\n");
chrigelburri 17:f0a973f17917 759 return(false);
chrigelburri 17:f0a973f17917 760 }
chrigelburri 17:f0a973f17917 761
chrigelburri 17:f0a973f17917 762 log("SetConfiguration\r\n");
chrigelburri 17:f0a973f17917 763 err = SetConfiguration(device,configuration);
chrigelburri 17:f0a973f17917 764 if (err < 0) {
chrigelburri 17:f0a973f17917 765 log("SetConfiguration error\r\n");
chrigelburri 17:f0a973f17917 766 return(false);
chrigelburri 17:f0a973f17917 767 }
chrigelburri 17:f0a973f17917 768
chrigelburri 17:f0a973f17917 769 log("interrupt setup\r\n");
chrigelburri 17:f0a973f17917 770 //interrupt setup
chrigelburri 17:f0a973f17917 771 if (IO_PENDING!=USBBulkTransfer(_device,input_ep|0x80,readbuff,sizeof(readbuff),AdbreadCallback,NULL)) return(ret);
chrigelburri 17:f0a973f17917 772
chrigelburri 17:f0a973f17917 773 log("ADB Standby\r\n");
chrigelburri 17:f0a973f17917 774 ret = true;
chrigelburri 17:f0a973f17917 775
chrigelburri 17:f0a973f17917 776 return(ret);
chrigelburri 17:f0a973f17917 777 }
chrigelburri 17:f0a973f17917 778
chrigelburri 17:f0a973f17917 779
chrigelburri 17:f0a973f17917 780 void desconnect(void)
chrigelburri 17:f0a973f17917 781 {
chrigelburri 17:f0a973f17917 782 ADB::closeAll();
chrigelburri 17:f0a973f17917 783 _device = 0;
chrigelburri 17:f0a973f17917 784 connected = false;
chrigelburri 17:f0a973f17917 785 }
chrigelburri 17:f0a973f17917 786
chrigelburri 17:f0a973f17917 787 /**
chrigelburri 17:f0a973f17917 788 * Write a set of bytes to an open ADB connection.
chrigelburri 17:f0a973f17917 789 *
chrigelburri 17:f0a973f17917 790 * @param connection ADB connection to write the data to.
chrigelburri 17:f0a973f17917 791 * @param length number of bytes to transmit.
chrigelburri 17:f0a973f17917 792 * @param data data to send.
chrigelburri 17:f0a973f17917 793 * @return number of transmitted bytes, or -1 on failure.
chrigelburri 17:f0a973f17917 794 */
chrigelburri 17:f0a973f17917 795 int ADB::write(Connection * connection, uint16_t length, uint8_t * data)
chrigelburri 17:f0a973f17917 796 {
chrigelburri 17:f0a973f17917 797 int ret;
chrigelburri 17:f0a973f17917 798
chrigelburri 17:f0a973f17917 799 // First check if we have a working ADB connection
chrigelburri 17:f0a973f17917 800 if (_device==0 || !connected) return -1;
chrigelburri 17:f0a973f17917 801
chrigelburri 17:f0a973f17917 802 // Check if the connection is open for writing.
chrigelburri 17:f0a973f17917 803 if (connection->status != ADB_OPEN) return -2;
chrigelburri 17:f0a973f17917 804
chrigelburri 17:f0a973f17917 805 // Write payload
chrigelburri 17:f0a973f17917 806 ret = ADB::writeMessage(_device, A_WRTE, connection->localID, connection->remoteID, length, data);
chrigelburri 17:f0a973f17917 807 if (ret==0)
chrigelburri 17:f0a973f17917 808 connection->status = ADB_WRITING;
chrigelburri 17:f0a973f17917 809
chrigelburri 17:f0a973f17917 810 return ret;
chrigelburri 17:f0a973f17917 811 }
chrigelburri 17:f0a973f17917 812
chrigelburri 17:f0a973f17917 813 /**
chrigelburri 17:f0a973f17917 814 * Write a string to an open ADB connection. The trailing zero is not transmitted.
chrigelburri 17:f0a973f17917 815 *
chrigelburri 17:f0a973f17917 816 * @param connection ADB connection to write the data to.
chrigelburri 17:f0a973f17917 817 * @param length number of bytes to transmit.
chrigelburri 17:f0a973f17917 818 * @param data data to send.
chrigelburri 17:f0a973f17917 819 * @return number of transmitted bytes, or -1 on failure.
chrigelburri 17:f0a973f17917 820 */
chrigelburri 17:f0a973f17917 821 int ADB::writeString(Connection * connection, char * str)
chrigelburri 17:f0a973f17917 822 {
chrigelburri 17:f0a973f17917 823 int ret;
chrigelburri 17:f0a973f17917 824
chrigelburri 17:f0a973f17917 825 // First check if we have a working ADB connection
chrigelburri 17:f0a973f17917 826 if (_device==0 || !connected) return -1;
chrigelburri 17:f0a973f17917 827
chrigelburri 17:f0a973f17917 828 // Check if the connection is open for writing.
chrigelburri 17:f0a973f17917 829 if (connection->status != ADB_OPEN) return -2;
chrigelburri 17:f0a973f17917 830
chrigelburri 17:f0a973f17917 831 // Write payload
chrigelburri 17:f0a973f17917 832 ret = ADB::writeStringMessage(_device, A_WRTE, connection->localID, connection->remoteID, str);
chrigelburri 17:f0a973f17917 833 if (ret==0)
chrigelburri 17:f0a973f17917 834 connection->status = ADB_WRITING;
chrigelburri 17:f0a973f17917 835
chrigelburri 17:f0a973f17917 836 return ret;
chrigelburri 17:f0a973f17917 837 }
chrigelburri 17:f0a973f17917 838
chrigelburri 17:f0a973f17917 839 /**
chrigelburri 17:f0a973f17917 840 * Write a set of bytes to this ADB connection.
chrigelburri 17:f0a973f17917 841 *
chrigelburri 17:f0a973f17917 842 * @param length number of bytes to transmit.
chrigelburri 17:f0a973f17917 843 * @param data data to send.
chrigelburri 17:f0a973f17917 844 * @return number of transmitted bytes, or -1 on failure.
chrigelburri 17:f0a973f17917 845 */
chrigelburri 17:f0a973f17917 846 int Connection::write(uint16_t length, uint8_t * data)
chrigelburri 17:f0a973f17917 847 {
chrigelburri 17:f0a973f17917 848 return ADB::write(this, length, data);
chrigelburri 17:f0a973f17917 849 }
chrigelburri 17:f0a973f17917 850
chrigelburri 17:f0a973f17917 851 /**
chrigelburri 17:f0a973f17917 852 * Write a string to this connection.
chrigelburri 17:f0a973f17917 853 *
chrigelburri 17:f0a973f17917 854 * @param length number of bytes to transmit.
chrigelburri 17:f0a973f17917 855 * @param data data to send.
chrigelburri 17:f0a973f17917 856 * @return number of transmitted bytes, or -1 on failure.
chrigelburri 17:f0a973f17917 857 */
chrigelburri 17:f0a973f17917 858 int Connection::writeString(char * str)
chrigelburri 17:f0a973f17917 859 {
chrigelburri 17:f0a973f17917 860 return ADB::writeString(this, str);
chrigelburri 17:f0a973f17917 861 }
chrigelburri 17:f0a973f17917 862
chrigelburri 17:f0a973f17917 863 /**
chrigelburri 17:f0a973f17917 864 * Checks if the connection is open for writing.
chrigelburri 17:f0a973f17917 865 * @return true iff the connection is open and ready to accept write commands.
chrigelburri 17:f0a973f17917 866 */
chrigelburri 17:f0a973f17917 867 bool Connection::isOpen()
chrigelburri 17:f0a973f17917 868 {
chrigelburri 17:f0a973f17917 869 return this->status == ADB_OPEN;
chrigelburri 17:f0a973f17917 870 }
chrigelburri 17:f0a973f17917 871
chrigelburri 17:f0a973f17917 872
chrigelburri 17:f0a973f17917 873 /** from USBHost load function. initialize Android device**/
chrigelburri 17:f0a973f17917 874 void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc) {
chrigelburri 17:f0a973f17917 875 char s[128];
chrigelburri 17:f0a973f17917 876
chrigelburri 17:f0a973f17917 877 log("LoadDevice %d %02X:%02X:%02X\r\n",device,interfaceDesc->bInterfaceClass,interfaceDesc->bInterfaceSubClass,interfaceDesc->bInterfaceProtocol);
chrigelburri 17:f0a973f17917 878
chrigelburri 17:f0a973f17917 879 for (int i = 1; i < 4; i++) {
chrigelburri 17:f0a973f17917 880 if (GetString(device,i,s,sizeof(s)) < 0)
chrigelburri 17:f0a973f17917 881 break;
chrigelburri 17:f0a973f17917 882 printf("%d: %s\r\n",i,s);
chrigelburri 17:f0a973f17917 883 }
chrigelburri 17:f0a973f17917 884
chrigelburri 17:f0a973f17917 885 // Adb?
chrigelburri 17:f0a973f17917 886 if(1)
chrigelburri 17:f0a973f17917 887 {
chrigelburri 17:f0a973f17917 888 ADB::isAdbDevice(device,1,2);
chrigelburri 17:f0a973f17917 889 }
chrigelburri 17:f0a973f17917 890
chrigelburri 17:f0a973f17917 891 }