ADKに対応していないAndroid端末にマイコンを繋いでADBインターフェースで通信できるMicroBridgeのmbed移植版。 mbedに繋いだサーボをAndroid端末から動かすサンプルプログラムです。 とりあえず暫定バージョンを公開します。 Dev Phone 1でのみ動作確認をしています。 USBのインターフェース番号を固定しているので他で繋がるかわかりません。

Dependencies:   TextLCD mbed

Committer:
jksoft
Date:
Sun Aug 21 14:36:35 2011 +0000
Revision:
0:dde3f92088d5

        

Who changed what in which revision?

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