├── .gitignore ├── Adb.cpp ├── Adb.h ├── LICENSE ├── README.md ├── Readme.txt ├── ch9.h ├── examples ├── Demo │ └── Demo.ino ├── Logcat │ └── Logcat.ino ├── Reboot │ └── Reboot.ino ├── SeeeduinoADKDemo │ └── SeeeduinoADKDemo.ino ├── Shell │ └── Shell.ino └── WriteFile │ └── WriteFile.ino ├── max3421e.cpp ├── max3421e.h ├── max3421e_constants.h ├── usb.cpp └── usb.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | 5 | # Libraries 6 | *.lib 7 | *.a 8 | 9 | # Shared objects (inc. Windows DLLs) 10 | *.dll 11 | *.so 12 | *.so.* 13 | *.dylib 14 | 15 | # Executables 16 | *.exe 17 | *.out 18 | *.app 19 | -------------------------------------------------------------------------------- /Adb.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Niels Brouwers 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | // #define DEBUG 21 | 22 | #define MAX_BUF_SIZE 256 23 | 24 | static usb_device * adbDevice; 25 | static Connection * firstConnection; 26 | static boolean connected; 27 | static int connectionLocalId = 1; 28 | 29 | // Event handler callback function. 30 | adb_eventHandler * eventHandler; 31 | 32 | // Forward declaration 33 | static void usbEventHandler(usb_device * device, usb_eventType event); 34 | 35 | /** 36 | * Initialises the ADB protocol. This function initialises the USB layer underneath so no further setup is required. 37 | */ 38 | void ADB::init() 39 | { 40 | // Signal that we are not connected. 41 | adbDevice = NULL; 42 | connected = false; 43 | 44 | // Initialise the USB layer and attach an event handler. 45 | USB::setEventHandler(usbEventHandler); 46 | USB::init(); 47 | } 48 | 49 | /** 50 | * Sets the ADB event handler function. This function will be called by the ADB layer 51 | * when interesting events occur, such as ADB connect/disconnect, connection open/close, and 52 | * connection writes from the ADB device. 53 | * 54 | * @param handler event handler function. 55 | */ 56 | void ADB::setEventHandler(adb_eventHandler * handler) 57 | { 58 | eventHandler = handler; 59 | } 60 | 61 | /** 62 | * Fires an ADB event. 63 | * @param connection ADB connection. May be NULL in case of global connect/disconnect events. 64 | * @param type event type. 65 | * @param length payload length or zero if no payload. 66 | * @param data payload data if relevant or NULL otherwise. 67 | */ 68 | void ADB::fireEvent(Connection * connection, adb_eventType type, uint16_t length, uint8_t * data) 69 | { 70 | // Fire the global event handler, if set. 71 | if (eventHandler!=NULL) 72 | eventHandler(connection, type, length, data); 73 | 74 | // Fire the event handler of the connection in question, if relevant 75 | if (connection!=NULL && connection->eventHandler!=NULL) 76 | connection->eventHandler(connection, type, length, data); 77 | } 78 | 79 | /** 80 | * Adds a new ADB connection. The connection string is per ADB specs, for example "tcp:1234" opens a 81 | * connection to tcp port 1234, and "shell:ls" outputs a listing of the phone root filesystem. Connections 82 | * can be made persistent by setting reconnect to true. Persistent connections will be automatically 83 | * reconnected when the USB cable is re-plugged in. Non-persistent connections will connect only once, 84 | * and should never be used after they are closed. 85 | * 86 | * The connection string is copied into the Connection record and may not exceed ADB_CONNECTIONSTRING_LENGTH-1 87 | * characters. 88 | * 89 | * @param connectionString ADB connectionstring. I.e. "tcp:1234" or "shell:ls". 90 | * @param reconnect true for automatic reconnect (persistent connections). 91 | * @param handler event handler. 92 | * @return an ADB connection record or NULL on failure (not enough slots or connection string too long). 93 | */ 94 | Connection * ADB::addConnection(const char * connectionString, boolean reconnect, adb_eventHandler * handler) 95 | { 96 | 97 | // Allocate a new ADB connection object 98 | Connection * connection = (Connection*)malloc(sizeof(Connection)); 99 | if (connection == NULL) return NULL; 100 | 101 | // Allocate memory for the connection string 102 | connection->connectionString = (char*)strdup(connectionString); 103 | if (connection->connectionString==NULL) 104 | { 105 | // Free the connection object and return null 106 | free(connection); 107 | return NULL; 108 | } 109 | 110 | // Initialise the newly created object. 111 | connection->localID = connectionLocalId ++; 112 | connection->status = ADB_CLOSED; 113 | connection->lastConnectionAttempt = 0; 114 | connection->reconnect = reconnect; 115 | connection->eventHandler = handler; 116 | 117 | // Add the connection to the linked list. Note that it's easier to just insert 118 | // at position 0 because you don't have to traverse the list :) 119 | connection->next = firstConnection; 120 | firstConnection = connection; 121 | 122 | // Unable to find an empty spot, all connection slots in use. 123 | return connection; 124 | } 125 | 126 | // Androide >= 4.2 requires authentication for an adb connection 127 | // This response sends a dummy public key. On the phone you 128 | // have to approve the key each time the cable is connected 129 | // https://code.google.com/p/microbridge/issues/detail?id=21 130 | void ADB::handleAuthenticate(adb_message * message) 131 | { 132 | uint32_t numBytes = message->data_length; 133 | uint32_t bytesLeft = numBytes; 134 | uint8_t buf[ADB_USB_PACKETSIZE]; 135 | ConnectionStatus previousStatus; 136 | int bytesRead; 137 | int len = bytesLeft < ADB_USB_PACKETSIZE ? bytesLeft : ADB_USB_PACKETSIZE; 138 | 139 | // Read payload 140 | bytesRead = USB::bulkRead(adbDevice, len, buf, false); 141 | while(bytesLeft > 0) 142 | { 143 | int len = bytesLeft < ADB_USB_PACKETSIZE ? bytesLeft : ADB_USB_PACKETSIZE; 144 | 145 | // Read payload 146 | bytesRead = USB::bulkRead(adbDevice, len, buf, false); 147 | 148 | // Break out of the read loop if there's no data to read :( 149 | if (bytesRead==-1) break; 150 | 151 | bytesLeft -= bytesRead; 152 | } 153 | 154 | ADB::writeStringMessage(adbDevice, A_AUTH, ADB_AUTH_RSAPUBLICKEY, NULL, "Chad AUTH"); 155 | while(!ADB::pollMessage(message, true)) 156 | delay(1); 157 | if(message->command == A_CNXN) 158 | ADB::handleConnect(message); 159 | // else 160 | // { 161 | // Serial.println("Unexpected response: "); 162 | // Serial.println(message->command,HEX); 163 | // } 164 | } 165 | 166 | 167 | /** 168 | * Prints an ADB_message, for debugging purposes. 169 | * @param message ADB message to print. 170 | */ 171 | #ifdef DEBUG 172 | static void adb_printMessage(adb_message * message) 173 | { 174 | switch(message->command) 175 | { 176 | case A_OKAY: 177 | serialPrintf("OKAY message [%lx] %ld %ld\n", message->command, message->arg0, message->arg1); 178 | break; 179 | case A_CLSE: 180 | serialPrintf("CLSE message [%lx] %ld %ld\n", message->command, message->arg0, message->arg1); 181 | break; 182 | case A_WRTE: 183 | serialPrintf("WRTE message [%lx] %ld %ld, %ld bytes\n", message->command, message->arg0, message->arg1, message->data_length); 184 | break; 185 | case A_CNXN: 186 | serialPrintf("CNXN message [%lx] %ld %ld\n", message->command, message->arg0, message->arg1); 187 | break; 188 | case A_SYNC: 189 | serialPrintf("SYNC message [%lx] %ld %ld\n", message->command, message->arg0, message->arg1); 190 | break; 191 | case A_OPEN: 192 | serialPrintf("OPEN message [%lx] %ld %ld\n", message->command, message->arg0, message->arg1); 193 | break; 194 | default: 195 | serialPrintf("WTF message [%lx] %ld %ld\n", message->command, message->arg0, message->arg1); 196 | break; 197 | } 198 | } 199 | #endif 200 | 201 | /** 202 | * Writes an empty message (without payload) to the ADB device. 203 | * 204 | * @param device USB device handle. 205 | * @param command ADB command. 206 | * @param arg0 first ADB argument (command dependent). 207 | * @param arg0 second ADB argument (command dependent). 208 | * @return error code or 0 for success. 209 | */ 210 | int ADB::writeEmptyMessage(usb_device * device, uint32_t command, uint32_t arg0, uint32_t arg1) 211 | { 212 | adb_message message; 213 | 214 | message.command = command; 215 | message.arg0 = arg0; 216 | message.arg1 = arg1; 217 | message.data_length = 0; 218 | message.data_check = 0; 219 | message.magic = command ^ 0xffffffff; 220 | 221 | #ifdef DEBUG 222 | serialPrint("OUT << "); adb_printMessage(&message); 223 | #endif 224 | 225 | return USB::bulkWrite(device, sizeof(adb_message), (uint8_t*)&message); 226 | } 227 | 228 | /** 229 | * Writes an ADB message with payload to the ADB device. 230 | * 231 | * @param device USB device handle. 232 | * @param command ADB command. 233 | * @param arg0 first ADB argument (command dependent). 234 | * @param arg0 second ADB argument (command dependent). 235 | * @param length payload length. 236 | * @param data command payload. 237 | * @return error code or 0 for success. 238 | */ 239 | int ADB::writeMessage(usb_device * device, uint32_t command, uint32_t arg0, uint32_t arg1, uint32_t length, uint8_t * data) 240 | { 241 | adb_message message; 242 | uint32_t count, sum = 0; 243 | uint8_t * x; 244 | uint8_t rcode; 245 | 246 | // Calculate data checksum 247 | count = length; 248 | x = data; 249 | while(count-- > 0) sum += *x++; 250 | 251 | // Fill out the message record. 252 | message.command = command; 253 | message.arg0 = arg0; 254 | message.arg1 = arg1; 255 | message.data_length = length; 256 | message.data_check = sum; 257 | message.magic = command ^ 0xffffffff; 258 | 259 | #ifdef DEBUG 260 | serialPrint("OUT << "); adb_printMessage(&message); 261 | #endif 262 | 263 | rcode = USB::bulkWrite(device, sizeof(adb_message), (uint8_t*)&message); 264 | if (rcode) return rcode; 265 | 266 | rcode = USB::bulkWrite(device, length, data); 267 | return rcode; 268 | } 269 | 270 | /** 271 | * Writes an ADB command with a string as payload. 272 | * 273 | * @param device USB device handle. 274 | * @param command ADB command. 275 | * @param arg0 first ADB argument (command dependent). 276 | * @param arg0 second ADB argument (command dependent). 277 | * @param str payload string. 278 | * @return error code or 0 for success. 279 | */ 280 | int ADB::writeStringMessage(usb_device * device, uint32_t command, uint32_t arg0, uint32_t arg1, char * str) 281 | { 282 | return ADB::writeMessage(device, command, arg0, arg1, strlen(str) + 1, (uint8_t*)str); 283 | } 284 | 285 | /** 286 | * Poll an ADB message. 287 | * @param message on success, the ADB message will be returned in this struct. 288 | * @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) 289 | * @return true iff a packet was successfully received, false otherwise. 290 | */ 291 | boolean ADB::pollMessage(adb_message * message, boolean poll) 292 | { 293 | int bytesRead; 294 | uint8_t buf[ADB_USB_PACKETSIZE]; 295 | 296 | // Poll a packet from the USB 297 | bytesRead = USB::bulkRead(adbDevice, ADB_USB_PACKETSIZE, buf, poll); 298 | 299 | // Check if the USB in transfer was successful. 300 | if (bytesRead<0) return false; 301 | 302 | // Check if the buffer contains a valid message 303 | memcpy((void*)message, (void*)buf, sizeof(adb_message)); 304 | 305 | // If the message is corrupt, return. 306 | if (message->magic != (message->command ^ 0xffffffff)) 307 | { 308 | #ifdef DEBUG 309 | serialPrintf("Broken message, magic mismatch, %d bytes\n", bytesRead); 310 | return false; 311 | #endif 312 | } 313 | 314 | // Check if the received number of bytes matches our expected 24 bytes of ADB message header. 315 | if (bytesRead != sizeof(adb_message)) return false; 316 | 317 | return true; 318 | } 319 | 320 | /** 321 | * Sends an ADB OPEN message for any connections that are currently in the CLOSED state. 322 | */ 323 | void ADB::openClosedConnections() 324 | { 325 | uint32_t timeSinceLastConnect; 326 | Connection * connection; 327 | 328 | // Iterate over the connection list and send "OPEN" for the ones that are currently closed. 329 | for (connection = firstConnection; connection!=NULL; connection = connection->next) 330 | { 331 | timeSinceLastConnect = millis() - connection->lastConnectionAttempt; 332 | if (connection->status==ADB_CLOSED && timeSinceLastConnect>ADB_CONNECTION_RETRY_TIME) 333 | { 334 | // Issue open command. 335 | ADB::writeStringMessage(adbDevice, A_OPEN, connection->localID, 0, connection->connectionString); 336 | 337 | // Record the last attempt time 338 | connection->lastConnectionAttempt = millis(); 339 | connection->status = ADB_OPENING; 340 | 341 | } 342 | } 343 | 344 | } 345 | 346 | /** 347 | * Handles and ADB OKAY message, which represents a transition in the connection state machine. 348 | * 349 | * @param connection ADB connection 350 | * @param message ADB message struct. 351 | */ 352 | void ADB::handleOkay(Connection * connection, adb_message * message) 353 | { 354 | // Check if the OKAY message was a response to a CONNECT message. 355 | if (connection->status==ADB_OPENING) 356 | { 357 | connection->status = ADB_OPEN; 358 | connection->remoteID = message->arg0; 359 | 360 | ADB::fireEvent(connection, ADB_CONNECTION_OPEN, 0, NULL); 361 | } 362 | 363 | // Check if the OKAY message was a response to a WRITE message. 364 | if (connection->status == ADB_WRITING) 365 | connection->status = ADB_OPEN; 366 | 367 | } 368 | 369 | /** 370 | * Handles an ADB CLOSE message, and fires an ADB event accordingly. 371 | * 372 | * @param connection ADB connection 373 | */ 374 | void ADB::handleClose(Connection * connection) 375 | { 376 | // Check if the CLOSE message was a response to a CONNECT message. 377 | if (connection->status==ADB_OPENING) 378 | ADB::fireEvent(connection, ADB_CONNECTION_FAILED, 0, NULL); 379 | else 380 | ADB::fireEvent(connection, ADB_CONNECTION_CLOSE, 0, NULL); 381 | 382 | // Connection failed 383 | if (connection->reconnect) 384 | connection->status = ADB_CLOSED; 385 | else 386 | connection->status = ADB_UNUSED; 387 | 388 | } 389 | 390 | /** 391 | * Handles an ADB WRITE message. 392 | * 393 | * @param connection ADB connection 394 | * @param message ADB message struct. 395 | */ 396 | void ADB::handleWrite(Connection * connection, adb_message * message) 397 | { 398 | uint32_t bytesLeft = message->data_length; 399 | uint8_t buf[ADB_USB_PACKETSIZE]; 400 | ConnectionStatus previousStatus; 401 | int bytesRead; 402 | 403 | previousStatus = connection->status; 404 | 405 | connection->status = ADB_RECEIVING; 406 | connection->dataRead = 0; 407 | connection->dataSize = message->data_length; 408 | 409 | while (bytesLeft>0) 410 | { 411 | int len = bytesLeft < ADB_USB_PACKETSIZE ? bytesLeft : ADB_USB_PACKETSIZE; 412 | 413 | // Read payload 414 | bytesRead = USB::bulkRead(adbDevice, len, buf, false); 415 | 416 | // if (len != bytesRead) 417 | // serialPrintf("bytes read mismatch: %d expected, %d read, %ld left\n", len, bytesRead, bytesLeft); 418 | 419 | // Break out of the read loop if there's no data to read :( 420 | if (bytesRead==-1) break; 421 | 422 | connection->dataRead += len; 423 | ADB::fireEvent(connection, ADB_CONNECTION_RECEIVE, len, buf); 424 | 425 | bytesLeft -= bytesRead; 426 | } 427 | 428 | // Send OKAY message in reply. 429 | bytesRead = ADB::writeEmptyMessage(adbDevice, A_OKAY, message->arg1, message->arg0); 430 | 431 | connection->status = previousStatus; 432 | } 433 | 434 | /** 435 | * Close all ADB connections. 436 | * 437 | * @param connection ADB connection 438 | * @param message ADB message struct. 439 | */ 440 | void ADB::closeAll() 441 | { 442 | Connection * connection; 443 | 444 | // Iterate over all connections and close the ones that are currently open. 445 | for (connection = firstConnection; connection != NULL; connection = connection->next) 446 | if (!(connection->status==ADB_UNUSED || connection->status==ADB_CLOSED)) 447 | ADB::handleClose(connection); 448 | 449 | } 450 | 451 | /** 452 | * Handles an ADB connect message. This is a response to a connect message sent from our side. 453 | * @param message ADB message. 454 | */ 455 | void ADB::handleConnect(adb_message * message) 456 | { 457 | unsigned int bytesRead; 458 | uint8_t buf[MAX_BUF_SIZE]; 459 | uint16_t len; 460 | 461 | // Read payload (remote ADB device ID) 462 | len = message->data_length < MAX_BUF_SIZE ? message->data_length : MAX_BUF_SIZE; 463 | bytesRead = USB::bulkRead(adbDevice, len, buf, false); 464 | 465 | // Signal that we are now connected to an Android device (yay!) 466 | connected = true; 467 | 468 | // Fire event. 469 | ADB::fireEvent(NULL, ADB_CONNECT, len, buf); 470 | 471 | } 472 | 473 | /** 474 | * This method is called periodically to check for new messages on the USB bus and process them. 475 | */ 476 | //void ADB::poll() 477 | // https://code.google.com/p/microbridge/issues/detail?id=21 478 | boolean ADB::poll() 479 | { 480 | Connection * connection; 481 | adb_message message; 482 | 483 | // Poll the USB layer. 484 | USB::poll(); 485 | 486 | // If no USB device, there's no work for us to be done, so just return. 487 | //if (adbDevice==NULL) return; 488 | // https://code.google.com/p/microbridge/issues/detail?id=21 489 | if (adbDevice == NULL) 490 | return false; 491 | 492 | // If not connected, send a connection string to the device. 493 | if (!connected) 494 | { 495 | ADB::writeStringMessage(adbDevice, A_CNXN, 0x01000000, 4096, (char*)"host::microbridge"); 496 | delay(500); // Give the device some time to respond. 497 | } 498 | 499 | // If we are connected, check if there are connections that need to be opened 500 | //if (connected) 501 | 502 | // https://code.google.com/p/microbridge/issues/detail?id=21 503 | else // If we are connected, check if there are connections that need to be opened 504 | ADB::openClosedConnections(); 505 | 506 | // Check for an incoming ADB message. 507 | if (!ADB::pollMessage(&message, true)) 508 | // return; 509 | // https://code.google.com/p/microbridge/issues/detail?id=21 510 | return false; 511 | 512 | // Handle a response from the ADB device to our CONNECT message. 513 | if (message.command == A_CNXN) 514 | ADB::handleConnect(&message); 515 | // https://code.google.com/p/microbridge/issues/detail?id=21 516 | else if(message.command == A_AUTH) 517 | ADB::handleAuthenticate(&message); 518 | 519 | // Handle messages for specific connections 520 | for (connection = firstConnection; connection != NULL; connection = connection->next) 521 | { 522 | if (connection->status!=ADB_UNUSED && connection->localID==message.arg1) 523 | { 524 | switch(message.command) 525 | { 526 | case A_OKAY: 527 | ADB::handleOkay(connection, &message); 528 | break; 529 | case A_CLSE: 530 | ADB::handleClose(connection); 531 | break; 532 | case A_WRTE: 533 | ADB::handleWrite(connection, &message); 534 | break; 535 | default: 536 | break; 537 | } 538 | } 539 | } 540 | 541 | // https://code.google.com/p/microbridge/issues/detail?id=21 542 | return true; 543 | } 544 | 545 | /** 546 | * Helper function for usb_isAdbDevice to check whether an interface is a valid ADB interface. 547 | * @param interface interface descriptor struct. 548 | */ 549 | boolean ADB::isAdbInterface(usb_interfaceDescriptor * interface) 550 | { 551 | 552 | // Check if the interface has exactly two endpoints. 553 | if (interface->bNumEndpoints!=2) return false; 554 | 555 | // Check if the endpoint supports bulk transfer. 556 | if (interface->bInterfaceProtocol != ADB_PROTOCOL) return false; 557 | if (interface->bInterfaceClass != ADB_CLASS) return false; 558 | if (interface->bInterfaceSubClass != ADB_SUBCLASS) return false; 559 | 560 | return true; 561 | } 562 | 563 | /** 564 | * Checks whether the a connected USB device is an ADB device and populates a configuration record if it is. 565 | * 566 | * @param device USB device. 567 | * @param handle pointer to a configuration record. The endpoint device address, configuration, and endpoint information will be stored here. 568 | * @return true iff the device is an ADB device. 569 | */ 570 | boolean ADB::isAdbDevice(usb_device * device, int configuration, adb_usbConfiguration * handle) 571 | { 572 | boolean ret = false; 573 | uint8_t buf[MAX_BUF_SIZE]; 574 | int bytesRead; 575 | 576 | // Read the length of the configuration descriptor. 577 | bytesRead = USB::getConfigurationDescriptor(device, configuration, MAX_BUF_SIZE, buf); 578 | if (bytesRead<0) return false; 579 | 580 | int pos = 0; 581 | uint8_t descriptorLength; 582 | uint8_t descriptorType; 583 | 584 | usb_configurationDescriptor * config = NULL; 585 | usb_interfaceDescriptor * interface = NULL; 586 | usb_endpointDescriptor * endpoint = NULL; 587 | 588 | while (pos < bytesRead) 589 | { 590 | descriptorLength = buf[pos]; 591 | descriptorType = buf[pos + 1]; 592 | 593 | switch (descriptorType) 594 | { 595 | case (USB_DESCRIPTOR_CONFIGURATION): 596 | config = (usb_configurationDescriptor *)(buf + pos); 597 | break; 598 | case (USB_DESCRIPTOR_INTERFACE): 599 | interface = (usb_interfaceDescriptor *)(buf + pos); 600 | 601 | if (ADB::isAdbInterface(interface)) 602 | { 603 | // handle->address = address; 604 | handle->configuration = config->bConfigurationValue; 605 | handle->interface = interface->bInterfaceNumber; 606 | 607 | // Detected ADB interface! 608 | ret = true; 609 | } 610 | break; 611 | case (USB_DESCRIPTOR_ENDPOINT): 612 | endpoint = (usb_endpointDescriptor *)(buf + pos); 613 | 614 | // If this endpoint descriptor is found right after the ADB interface descriptor, it belong to that interface. 615 | if (interface->bInterfaceNumber == handle->interface) 616 | { 617 | if (endpoint->bEndpointAddress & 0x80) 618 | handle->inputEndPointAddress = endpoint->bEndpointAddress & ~0x80; 619 | else 620 | handle->outputEndPointAddress = endpoint->bEndpointAddress; 621 | } 622 | 623 | break; 624 | default: 625 | break; 626 | } 627 | 628 | pos += descriptorLength; 629 | } 630 | 631 | return ret; 632 | 633 | } 634 | 635 | /** 636 | * Initialises an ADB device. 637 | * 638 | * @param device the USB device. 639 | * @param configuration configuration information. 640 | */ 641 | void ADB::initUsb(usb_device * device, adb_usbConfiguration * handle) 642 | { 643 | // Initialise/configure the USB device. 644 | // TODO write a usb_initBulkDevice function? 645 | USB::initDevice(device, handle->configuration); 646 | 647 | // Initialise bulk input endpoint. 648 | USB::initEndPoint(&(device->bulk_in), handle->inputEndPointAddress); 649 | device->bulk_in.attributes = USB_TRANSFER_TYPE_BULK; 650 | device->bulk_in.maxPacketSize = ADB_USB_PACKETSIZE; 651 | 652 | // Initialise bulk output endpoint. 653 | USB::initEndPoint(&(device->bulk_out), handle->outputEndPointAddress); 654 | device->bulk_out.attributes = USB_TRANSFER_TYPE_BULK; 655 | device->bulk_out.maxPacketSize = ADB_USB_PACKETSIZE; 656 | 657 | // Success, signal that we are now connected. 658 | adbDevice = device; 659 | } 660 | 661 | /** 662 | * Handles events from the USB layer. 663 | * 664 | * @param device USB device that generated the event. 665 | * @param event USB event. 666 | */ 667 | static void usbEventHandler(usb_device * device, usb_eventType event) 668 | { 669 | adb_usbConfiguration handle; 670 | 671 | switch (event) 672 | { 673 | case USB_CONNECT: 674 | 675 | // Check if the newly connected device is an ADB device, and initialise it if so. 676 | if (ADB::isAdbDevice(device, 0, &handle)) 677 | ADB::initUsb(device, &handle); 678 | 679 | break; 680 | 681 | case USB_DISCONNECT: 682 | 683 | // Check if the device that was disconnected is the ADB device we've been using. 684 | if (device == adbDevice) 685 | { 686 | // Close all open ADB connections. 687 | ADB::closeAll(); 688 | 689 | // Signal that we're no longer connected by setting the global device handler to NULL; 690 | adbDevice = NULL; 691 | connected = false; 692 | } 693 | 694 | break; 695 | 696 | default: 697 | // ignore 698 | break; 699 | } 700 | } 701 | 702 | /** 703 | * Write a set of bytes to an open ADB connection. 704 | * 705 | * @param connection ADB connection to write the data to. 706 | * @param length number of bytes to transmit. 707 | * @param data data to send. 708 | * @return number of transmitted bytes, or -1 on failure. 709 | */ 710 | int ADB::write(Connection * connection, uint16_t length, uint8_t * data) 711 | { 712 | int ret; 713 | 714 | // First check if we have a working ADB connection 715 | if (adbDevice==NULL || !connected) return -1; 716 | 717 | // Check if the connection is open for writing. 718 | if (connection->status != ADB_OPEN) return -2; 719 | 720 | // Write payload 721 | ret = ADB::writeMessage(adbDevice, A_WRTE, connection->localID, connection->remoteID, length, data); 722 | if (ret==0) 723 | connection->status = ADB_WRITING; 724 | 725 | return ret; 726 | } 727 | 728 | /** 729 | * Write a string to an open ADB connection. The trailing zero is not transmitted. 730 | * 731 | * @param connection ADB connection to write the data to. 732 | * @param length number of bytes to transmit. 733 | * @param data data to send. 734 | * @return number of transmitted bytes, or -1 on failure. 735 | */ 736 | int ADB::writeString(Connection * connection, char * str) 737 | { 738 | int ret; 739 | 740 | // First check if we have a working ADB connection 741 | if (adbDevice==NULL || !connected) return -1; 742 | 743 | // Check if the connection is open for writing. 744 | if (connection->status != ADB_OPEN) return -2; 745 | 746 | // Write payload 747 | ret = ADB::writeStringMessage(adbDevice, A_WRTE, connection->localID, connection->remoteID, str); 748 | if (ret==0) 749 | connection->status = ADB_WRITING; 750 | 751 | return ret; 752 | } 753 | 754 | /** 755 | * Write a set of bytes to this ADB connection. 756 | * 757 | * @param length number of bytes to transmit. 758 | * @param data data to send. 759 | * @return number of transmitted bytes, or -1 on failure. 760 | */ 761 | int Connection::write(uint16_t length, uint8_t * data) 762 | { 763 | return ADB::write(this, length, data); 764 | } 765 | 766 | /** 767 | * Write a string to this connection. 768 | * 769 | * @param length number of bytes to transmit. 770 | * @param data data to send. 771 | * @return number of transmitted bytes, or -1 on failure. 772 | */ 773 | int Connection::writeString(char * str) 774 | { 775 | return ADB::writeString(this, str); 776 | } 777 | 778 | /** 779 | * Checks if the connection is open for writing. 780 | * @return true iff the connection is open and ready to accept write commands. 781 | */ 782 | bool Connection::isOpen() 783 | { 784 | return this->status == ADB_OPEN; 785 | } 786 | 787 | -------------------------------------------------------------------------------- /Adb.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Niels Brouwers 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License.#include 15 | */ 16 | 17 | #ifndef __adb_h__ 18 | #define __adb_h__ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | typedef void(usb_eventHandler)(usb_device * device, usb_eventType event); 25 | 26 | #define MAX_PAYLOAD 4096; 27 | 28 | #define A_SYNC 0x434e5953 29 | #define A_CNXN 0x4e584e43 30 | #define A_OPEN 0x4e45504f 31 | #define A_OKAY 0x59414b4f 32 | #define A_CLSE 0x45534c43 33 | #define A_WRTE 0x45545257 34 | 35 | // https://code.google.com/p/microbridge/issues/detail?id=21 36 | #define A_AUTH 0x48545541 37 | 38 | #define ADB_CLASS 0xff 39 | #define ADB_SUBCLASS 0x42 40 | #define ADB_PROTOCOL 0x1 41 | 42 | #define ADB_USB_PACKETSIZE 0x40 43 | #define ADB_CONNECTION_RETRY_TIME 1000 44 | 45 | // https://code.google.com/p/microbridge/issues/detail?id=21 46 | /* AUTH packets first argument */ 47 | /* Request */ 48 | #define ADB_AUTH_TOKEN 1 49 | /* Response */ 50 | #define ADB_AUTH_SIGNATURE 2 51 | #define ADB_AUTH_RSAPUBLICKEY 3 52 | 53 | typedef struct 54 | { 55 | uint8_t address; 56 | uint8_t configuration; 57 | uint8_t interface; 58 | uint8_t inputEndPointAddress; 59 | uint8_t outputEndPointAddress; 60 | } adb_usbConfiguration; 61 | 62 | typedef struct 63 | { 64 | // Command identifier constant 65 | uint32_t command; 66 | 67 | // First argument 68 | uint32_t arg0; 69 | 70 | // Second argument 71 | uint32_t arg1; 72 | 73 | // Payload length (0 is allowed) 74 | uint32_t data_length; 75 | 76 | // Checksum of data payload 77 | uint32_t data_check; 78 | 79 | // Command ^ 0xffffffff 80 | uint32_t magic; 81 | 82 | } adb_message; 83 | 84 | // https://code.google.com/p/microbridge/issues/detail?id=21 85 | typedef struct 86 | { 87 | uint16_t a; 88 | uint16_t b; 89 | } rsa_key; 90 | 91 | typedef enum 92 | { 93 | ADB_UNUSED = 0, 94 | ADB_CLOSED, 95 | ADB_OPEN, 96 | ADB_OPENING, 97 | ADB_RECEIVING, 98 | ADB_WRITING 99 | } ConnectionStatus; 100 | 101 | typedef enum 102 | { 103 | ADB_CONNECT = 0, 104 | ADB_DISCONNECT, 105 | ADB_CONNECTION_OPEN, 106 | ADB_CONNECTION_CLOSE, 107 | ADB_CONNECTION_FAILED, 108 | ADB_CONNECTION_RECEIVE 109 | } adb_eventType; 110 | 111 | class Connection; 112 | 113 | // Event handler 114 | typedef void(adb_eventHandler)(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data); 115 | 116 | class Connection 117 | { 118 | private: 119 | public: 120 | char * connectionString; 121 | uint32_t localID, remoteID; 122 | uint32_t lastConnectionAttempt; 123 | uint16_t dataSize, dataRead; 124 | ConnectionStatus status; 125 | boolean reconnect; 126 | adb_eventHandler * eventHandler; 127 | Connection * next; 128 | 129 | int write(uint16_t length, uint8_t * data); 130 | int writeString(char * str); 131 | bool isOpen(); 132 | }; 133 | 134 | class ADB 135 | { 136 | 137 | private: 138 | static void fireEvent(Connection * connection, adb_eventType type, uint16_t length, uint8_t * data); 139 | static int writeEmptyMessage(usb_device * device, uint32_t command, uint32_t arg0, uint32_t arg1); 140 | static int writeMessage(usb_device * device, uint32_t command, uint32_t arg0, uint32_t arg1, uint32_t length, uint8_t * data); 141 | static int writeStringMessage(usb_device * device, uint32_t command, uint32_t arg0, uint32_t arg1, char * str); 142 | static boolean pollMessage(adb_message * message, boolean poll); 143 | static void openClosedConnections(); 144 | static void handleOkay(Connection * connection, adb_message * message); 145 | static void handleClose(Connection * connection); 146 | static void handleWrite(Connection * connection, adb_message * message); 147 | static void handleConnect(adb_message * message); 148 | 149 | // https://code.google.com/p/microbridge/issues/detail?id=21 150 | static void handleAuthenticate(adb_message * message); 151 | static boolean isAdbInterface(usb_interfaceDescriptor * interface); 152 | 153 | public: 154 | static void init(); 155 | // static void poll(); 156 | // https://code.google.com/p/microbridge/issues/detail?id=21 157 | static boolean poll(); 158 | 159 | static void setEventHandler(adb_eventHandler * handler); 160 | static Connection * addConnection(const char * connectionString, boolean reconnect, adb_eventHandler * eventHandler); 161 | static int write(Connection * connection, uint16_t length, uint8_t * data); 162 | static int writeString(Connection * connection, char * str); 163 | 164 | static boolean isAdbDevice(usb_device * device, int configuration, adb_usbConfiguration * handle); 165 | static void initUsb(usb_device * device, adb_usbConfiguration * handle); 166 | static void closeAll(); 167 | }; 168 | 169 | #endif 170 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | microbridge-arduino 2 | =================== 3 | 4 | This library is a modified version of MicroBridge downloaded from http://code.google.com/p/microbridge/. 5 | 6 | 1. Minor modification is done to correctly configure SPI port of Seeeduino ADK Main Board. 7 | This modification can also be used for any Any Android ADK Reference board 8 | 9 | 2. A new sketch SeeeduinoADKDemo.pde is added to showcase Seeeduino ADK Main Board. 10 | 11 | 3. Added fix for Android version >= 4.2 where an RSA key is required to connect to and use the ADB port. Fix was not discovered by me, but documented here https://code.google.com/p/microbridge/issues/detail?id=21 12 | 13 | --- 14 | ## Installation instructions 15 | 16 | 1. Download the [latest zip file](https://github.com/agoransson/microbridge-arduino/archive/master.zip). 17 | 2. Extract the zipfile into your `/libraries/` folder 18 | 3. Rename the new folder to `Adb` 19 | 4. Restart your Arduino IDE 20 | 21 | --- 22 | -------------------------------------------------------------------------------- /Readme.txt: -------------------------------------------------------------------------------- 1 | This library is a modified version of MicroBridge downloaded from http://code.google.com/p/microbridge/. 2 | 1.Minor modification is done to correctly configure SPI port of Seeeduino ADK Main Board. 3 | This modification can also be used for any Any Android ADK Reference board 4 | 5 | 2.A new sketch SeeeduinoADKDemo.pde is added to showcase Seeeduino ADK Main Board. 6 | -------------------------------------------------------------------------------- /ch9.h: -------------------------------------------------------------------------------- 1 | /* USB chapter 9 structures */ 2 | #ifndef _ch9_h_ 3 | #define _ch9_h_ 4 | 5 | /* Standard Device Requests */ 6 | #define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS 7 | #define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE 8 | #define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE 9 | #define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS 10 | #define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR 11 | #define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR 12 | #define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION 13 | #define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION 14 | #define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE 15 | #define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE 16 | #define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME 17 | 18 | #define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt 19 | #define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up 20 | #define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode 21 | 22 | /* Setup Data Constants */ 23 | 24 | #define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer 25 | #define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer 26 | #define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard 27 | #define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class 28 | #define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor 29 | #define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device 30 | #define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface 31 | #define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint 32 | #define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other 33 | 34 | /* USB descriptors */ 35 | 36 | #define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. 37 | #define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. 38 | #define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. 39 | #define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. 40 | #define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. 41 | #define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. 42 | #define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. 43 | #define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. 44 | #define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. 45 | 46 | /* OTG SET FEATURE Constants */ 47 | #define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP 48 | #define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP 49 | #define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP 50 | 51 | /* USB Endpoint Transfer Types */ 52 | #define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. 53 | #define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. 54 | #define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. 55 | #define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. 56 | #define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes 57 | 58 | 59 | /* Standard Feature Selectors for CLEAR_FEATURE Requests */ 60 | #define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient 61 | #define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient 62 | #define USB_FEATURE_TEST_MODE 2 // Device recipient 63 | 64 | /* HID constants. Not part of chapter 9 */ 65 | /* Class-Specific Requests */ 66 | #define HID_REQUEST_GET_REPORT 0x01 67 | #define HID_REQUEST_GET_IDLE 0x02 68 | #define HID_REQUEST_GET_PROTOCOL 0x03 69 | #define HID_REQUEST_SET_REPORT 0x09 70 | #define HID_REQUEST_SET_IDLE 0x0A 71 | #define HID_REQUEST_SET_PROTOCOL 0x0B 72 | 73 | /* Class Descriptor Types */ 74 | #define HID_DESCRIPTOR_HID 0x21 75 | #define HID_DESCRIPTOR_REPORT 0x22 76 | #define HID_DESRIPTOR_PHY 0x23 77 | 78 | /* Protocol Selection */ 79 | #define BOOT_PROTOCOL 0x00 80 | #define RPT_PROTOCOL 0x01 81 | 82 | /* HID Interface Class Code */ 83 | #define HID_INTF 0x03 84 | 85 | /* HID Interface Class SubClass Codes */ 86 | #define BOOT_INTF_SUBCLASS 0x01 87 | 88 | /* HID Interface Class Protocol Codes */ 89 | #define HID_PROTOCOL_NONE 0x00 90 | #define HID_PROTOCOL_KEYBOARD 0x01 91 | #define HID_PROTOCOL_MOUSE 0x02 92 | 93 | /* descriptor data structures */ 94 | 95 | #endif // _ch9_h_ 96 | -------------------------------------------------------------------------------- /examples/Demo/Demo.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Hardware servos 6 | Servo servos[2]; 7 | 8 | // Adb connection. 9 | Connection * connection; 10 | 11 | // Elapsed time for ADC sampling 12 | long lastTime; 13 | 14 | // Event handler for the shell connection. 15 | void adbEventHandler(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data) 16 | { 17 | int i; 18 | 19 | // Data packets contain two bytes, one for each servo, in the range of [0..180] 20 | if (event == ADB_CONNECTION_RECEIVE) 21 | { 22 | servos[0].write(data[0]); 23 | servos[1].write(data[1]); 24 | } 25 | 26 | } 27 | 28 | void setup() 29 | { 30 | 31 | // Initialise serial port 32 | Serial.begin(57600); 33 | 34 | // Note start time 35 | lastTime = millis(); 36 | 37 | // Attach servos 38 | servos[0].attach(2); 39 | servos[1].attach(3); 40 | 41 | // Initialise the ADB subsystem. 42 | ADB::init(); 43 | 44 | // Open an ADB stream to the phone's shell. Auto-reconnect 45 | connection = ADB::addConnection("tcp:4567", true, adbEventHandler); 46 | } 47 | 48 | void loop() 49 | { 50 | 51 | if ((millis() - lastTime) > 20) 52 | { 53 | uint16_t data = analogRead(A0); 54 | connection->write(2, (uint8_t*)&data); 55 | lastTime = millis(); 56 | } 57 | 58 | // Poll the ADB subsystem. 59 | ADB::poll(); 60 | } 61 | 62 | -------------------------------------------------------------------------------- /examples/Logcat/Logcat.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Event handler for the shell connection. 5 | void adbEventHandler(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data) 6 | { 7 | int i; 8 | 9 | if (event == ADB_CONNECTION_RECEIVE) 10 | for (i=0; i 2 | #include 3 | 4 | // Adb connection. 5 | Connection * shell; 6 | 7 | void setup() 8 | { 9 | 10 | // Initialise serial port 11 | Serial.begin(57600); 12 | 13 | // Initialise the ADB subsystem. 14 | ADB::init(); 15 | 16 | // Open an ADB stream to the phone's shell. Auto-reconnect 17 | shell = ADB::addConnection("shell:", true, NULL); 18 | } 19 | 20 | void loop() 21 | { 22 | 23 | // DFRobot romeo buttons are connected to analog input pin 0. 24 | if (analogRead(A7) == 0 && shell->isOpen()) 25 | shell->writeString("reboot\n"); 26 | 27 | // Poll the ADB subsystem. 28 | ADB::poll(); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /examples/SeeeduinoADKDemo/SeeeduinoADKDemo.ino: -------------------------------------------------------------------------------- 1 | //Seeeduino ADK Demo using Niels Brouwers' MicroBridge library. 2 | //Connect an LED to D12 and a variable resistor(POT) to A0 3 | 4 | #include 5 | #include 6 | 7 | // Adb connection. 8 | Connection * connection; 9 | 10 | // Elapsed time for ADC sampling. The rate at which ADC value is sent to Android device. 11 | long lastTime; 12 | 13 | //State of LED. Initially OFF. 14 | uint8_t LEDState=0; 15 | 16 | // Event handler for the shell connection. 17 | // This event handler is called whenever data is sent from Android Device to Seeeduino ADK. 18 | // Any data / command to be sent to I/O of ADK has to be handled here. 19 | // 20 | // For eg: 1.Controlling an ouput port 2.Interacting with a device connected 21 | // to ADK via IIC or Serial Port. 22 | 23 | void adbEventHandler(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data) 24 | { 25 | 26 | // In this example Data packets contain one byte and it decides the state of a LED connected to D12 27 | // The size of data is predetermined for this application. Android device also uses the same size. 28 | 29 | if (event == ADB_CONNECTION_RECEIVE) 30 | { 31 | if(LEDState != data[0]) 32 | { 33 | digitalWrite(12, data[0]); // Change the state of LED 34 | Serial.println(data[0],DEC); 35 | LEDState = data[0]; // Store the State of LED 36 | } 37 | } 38 | 39 | } 40 | 41 | void setup() 42 | { 43 | //Serial port debug purpose 44 | Serial.begin(57600); 45 | 46 | // Note start time 47 | lastTime = millis(); 48 | 49 | // Set Digital pin 12 (LED is connected) as output 50 | pinMode(12,OUTPUT); 51 | 52 | // Initialise the ADB subsystem. 53 | ADB::init(); 54 | 55 | // Open an ADB stream to the phone's shell. Auto-reconnect. Use any unused port number eg:4568 56 | connection = ADB::addConnection("tcp:4568", true, adbEventHandler); 57 | 58 | } 59 | 60 | void loop() 61 | { 62 | //Check if ADC needs to be sampled. 63 | if ((millis() - lastTime) > 20) 64 | { 65 | //Read ADC value 66 | uint16_t data = analogRead(A0); 67 | 68 | //Send the ADC value to Android device as two bytes of data. 69 | connection->write(2,(uint8_t*)&data); 70 | lastTime = millis(); 71 | } 72 | 73 | // Poll the ADB subsystem. 74 | ADB::poll(); 75 | } 76 | 77 | -------------------------------------------------------------------------------- /examples/Shell/Shell.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | Connection * shell; 5 | 6 | // Event handler for the shell connection. 7 | void adbEventHandler(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data) 8 | { 9 | int i; 10 | 11 | if (event == ADB_CONNECTION_RECEIVE) 12 | for (i=0; i 0) 36 | { 37 | // read the incoming byte: 38 | ch = Serial.read(); 39 | 40 | // Write to shell 41 | if (shell->status == ADB_OPEN) 42 | shell->write(1, &ch); 43 | else 44 | Serial.print("Shell not open"); 45 | 46 | } 47 | 48 | // Poll the ADB subsystem. 49 | ADB::poll(); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /examples/WriteFile/WriteFile.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void setup() 5 | { 6 | 7 | // Initialise serial port 8 | Serial.begin(57600); 9 | 10 | // Initialise the ADB subsystem. 11 | ADB::init(); 12 | 13 | // Execute the UNIX shell command 'echo "hello world" > /sdcard/hello', which creates a 14 | // new text file on the sd card called 'hello', containing the text 'hello world'. 15 | ADB::addConnection("shell:echo \"hello world\" > /sdcard/hello", false, NULL); 16 | } 17 | 18 | void loop() 19 | { 20 | // Poll the ADB subsystem. 21 | ADB::poll(); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /max3421e.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Niels Brouwers 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License.#include 15 | */ 16 | 17 | /** 18 | * 19 | * Library for the max3421e USB host controller shield produced by circuitsathome and Sparkfun. 20 | * This is a low-level interface that provides access to the internal registers and polls the 21 | * controller for state changes. 22 | * 23 | * This library is based on work done by Oleg Masurov, but has been ported to C and heavily 24 | * restructured. Control over the GPIO pins has been stripped. 25 | * 26 | * Note that the current incarnation of this library only supports the Arduino Mega with a 27 | * hardware mod to rewire the MISO, MOSI, and CLK SPI pins. 28 | * 29 | * http://www.circuitsathome.com/ 30 | */ 31 | 32 | #include 33 | #include 34 | #include "max3421e.h" 35 | #include "HardwareSerial.h" 36 | 37 | 38 | static uint8_t vbusState; 39 | 40 | /* 41 | * Initialises the max3421e host shield. Initialises the SPI bus and sets the required pin directions. 42 | * Must be called before powerOn. 43 | */ 44 | void max3421e_init() 45 | { 46 | 47 | SPI.begin(); 48 | 49 | pinMode(PIN_MAX_SS, OUTPUT); 50 | /* 51 | pinMode(PIN_MAX_INT, INPUT); 52 | pinMode(PIN_MAX_GPX, INPUT); 53 | pinMode(PIN_MAX_RESET, OUTPUT); 54 | */ 55 | 56 | 57 | DDRE &= ~ 0x40; 58 | DDRJ &= ~ 0x08; 59 | DDRJ |= 0x04; 60 | 61 | 62 | 63 | /* 64 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 65 | 66 | // Set MAX_INT and MAX_GPX pins to input mode. 67 | DDRH &= ~(0x40 | 0x20); 68 | 69 | // Set SPI !SS pint to output mode. 70 | DDRB |= 0x10; 71 | 72 | // Set RESET pin to output 73 | DDRH |= 0x10; 74 | 75 | #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) 76 | 77 | // Set MAX_INT and MAX_GPX pins to input mode. 78 | DDRB &= ~0x3; 79 | 80 | // Set RESET pin to output 81 | DDRD |= 0x80; 82 | 83 | // Set SS pin to output 84 | DDRB |= 0x4; 85 | 86 | #endif 87 | */ 88 | 89 | // Pull SPI !SS high 90 | MAX_SS(1); 91 | 92 | // Reset 93 | MAX_RESET(1); 94 | } 95 | 96 | /** 97 | * Resets the max3412e. Sets the chip reset bit, SPI configuration is not affected. 98 | * @return true iff success. 99 | */ 100 | boolean max3421e_reset(void) 101 | { 102 | uint8_t tmp = 0; 103 | 104 | // Chip reset. This stops the oscillator 105 | max3421e_write(MAX_REG_USBCTL, bmCHIPRES); 106 | 107 | // Remove the reset 108 | max3421e_write(MAX_REG_USBCTL, 0x00); 109 | 110 | delay(10); 111 | 112 | // Wait until the PLL is stable 113 | while (!(max3421e_read(MAX_REG_USBIRQ) & bmOSCOKIRQ)) 114 | { 115 | // Timeout after 256 attempts. 116 | tmp++; 117 | if (tmp == 0) 118 | return (false); 119 | } 120 | 121 | // Success. 122 | return (true); 123 | } 124 | 125 | /** 126 | * Initialises the max3421e after power-on. 127 | */ 128 | void max3421e_powerOn(void) 129 | { 130 | // Configure full-duplex SPI, interrupt pulse. 131 | max3421e_write(MAX_REG_PINCTL, (bmFDUPSPI + bmINTLEVEL + bmGPXB)); //Full-duplex SPI, level interrupt, GPX 132 | 133 | // Stop/start the oscillator. 134 | if (max3421e_reset() == false) 135 | Serial.print("Error: OSCOKIRQ failed to assert\n"); 136 | 137 | // Configure host operation. 138 | max3421e_write(MAX_REG_MODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ ); // set pull-downs, Host, Separate GPIN IRQ on GPX 139 | max3421e_write(MAX_REG_HIEN, bmCONDETIE | bmFRAMEIE ); //connection detection 140 | 141 | // Check if device is connected. 142 | max3421e_write(MAX_REG_HCTL, bmSAMPLEBUS ); // sample USB bus 143 | while (!(max3421e_read(MAX_REG_HCTL) & bmSAMPLEBUS)); //wait for sample operation to finish 144 | 145 | max3421e_busprobe(); //check if anything is connected 146 | max3421e_write(MAX_REG_HIRQ, bmCONDETIRQ ); //clear connection detect interrupt 147 | 148 | // Enable interrupt pin. 149 | max3421e_write(MAX_REG_CPUCTL, 0x01); 150 | } 151 | 152 | /** 153 | * Writes a single register. 154 | * 155 | * @param reg register address. 156 | * @param value value to write. 157 | */ 158 | void max3421e_write(uint8_t reg, uint8_t value) 159 | { 160 | // Pull slave select low to indicate start of transfer. 161 | MAX_SS(0); 162 | 163 | // Transfer command byte, 0x02 indicates write. 164 | SPDR = (reg | 0x02); 165 | while (!(SPSR & (1 << SPIF))); 166 | 167 | // Transfer value byte. 168 | SPDR = value; 169 | while (!(SPSR & (1 << SPIF))); 170 | 171 | // Pull slave select high to indicate end of transfer. 172 | MAX_SS(1); 173 | 174 | return; 175 | } 176 | 177 | /** 178 | * Writes multiple bytes to a register. 179 | * @param reg register address. 180 | * @param count number of bytes to write. 181 | * @param vaues input values. 182 | * @return a pointer to values, incremented by the number of bytes written (values + length). 183 | */ 184 | uint8_t * max3421e_writeMultiple(uint8_t reg, uint8_t count, uint8_t * values) 185 | { 186 | // Pull slave select low to indicate start of transfer. 187 | MAX_SS(0); 188 | 189 | // Transfer command byte, 0x02 indicates write. 190 | SPDR = (reg | 0x02); 191 | while (!(SPSR & (1 << SPIF))); 192 | 193 | // Transfer values. 194 | while (count--) 195 | { 196 | // Send next value byte. 197 | SPDR = (*values); 198 | while (!(SPSR & (1 << SPIF))); 199 | 200 | values++; 201 | } 202 | 203 | // Pull slave select high to indicate end of transfer. 204 | MAX_SS(1); 205 | 206 | return (values); 207 | } 208 | 209 | /** 210 | * Reads a single register. 211 | * 212 | * @param reg register address. 213 | * @return result value. 214 | */ 215 | uint8_t max3421e_read(uint8_t reg) 216 | { 217 | // Pull slave-select high to initiate transfer. 218 | MAX_SS(0); 219 | 220 | // Send a command byte containing the register number. 221 | SPDR = reg; 222 | while (!(SPSR & (1 << SPIF))); 223 | 224 | // Send an empty byte while reading. 225 | SPDR = 0; 226 | while (!(SPSR & (1 << SPIF))); 227 | 228 | // Pull slave-select low to signal transfer complete. 229 | MAX_SS(1); 230 | 231 | // Return result byte. 232 | return (SPDR); 233 | } 234 | 235 | /** 236 | * Reads multiple bytes from a register. 237 | * 238 | * @param reg register to read from. 239 | * @param count number of bytes to read. 240 | * @param values target buffer. 241 | * @return pointer to the input buffer + count. 242 | */ 243 | uint8_t * max3421e_readMultiple(uint8_t reg, uint8_t count, uint8_t * values) 244 | { 245 | // Pull slave-select high to initiate transfer. 246 | MAX_SS(0); 247 | 248 | // Send a command byte containing the register number. 249 | SPDR = reg; 250 | while (!(SPSR & (1 << SPIF))); //wait 251 | 252 | // Read [count] bytes. 253 | while (count--) 254 | { 255 | // Send empty byte while reading. 256 | SPDR = 0; 257 | while (!(SPSR & (1 << SPIF))); 258 | 259 | *values = SPDR; 260 | values++; 261 | } 262 | 263 | // Pull slave-select low to signal transfer complete. 264 | MAX_SS(1); 265 | 266 | // Return the byte array + count. 267 | return (values); 268 | } 269 | 270 | /** 271 | * @return the status of Vbus. 272 | */ 273 | uint8_t max3421e_getVbusState() 274 | { 275 | return vbusState; 276 | } 277 | 278 | /** 279 | * Probes the bus to determine device presence and speed, and switches host to this speed. 280 | */ 281 | void max3421e_busprobe(void) 282 | { 283 | uint8_t bus_sample; 284 | bus_sample = max3421e_read(MAX_REG_HRSL); //Get J,K status 285 | bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the uint8_t 286 | 287 | switch (bus_sample) 288 | { 289 | //start full-speed or low-speed host 290 | case (bmJSTATUS): 291 | if ((max3421e_read(MAX_REG_MODE) & bmLOWSPEED) == 0) 292 | { 293 | max3421e_write(MAX_REG_MODE, MODE_FS_HOST ); //start full-speed host 294 | vbusState = FSHOST; 295 | } else 296 | { 297 | max3421e_write(MAX_REG_MODE, MODE_LS_HOST); //start low-speed host 298 | vbusState = LSHOST; 299 | } 300 | break; 301 | case (bmKSTATUS): 302 | if ((max3421e_read(MAX_REG_MODE) & bmLOWSPEED) == 0) 303 | { 304 | max3421e_write(MAX_REG_MODE, MODE_LS_HOST ); //start low-speed host 305 | vbusState = LSHOST; 306 | } else 307 | { 308 | max3421e_write(MAX_REG_MODE, MODE_FS_HOST ); //start full-speed host 309 | vbusState = FSHOST; 310 | } 311 | break; 312 | case (bmSE1): //illegal state 313 | vbusState = SE1; 314 | break; 315 | case (bmSE0): //disconnected state 316 | vbusState = SE0; 317 | break; 318 | } 319 | } 320 | 321 | /** 322 | * MAX3421 state change task and interrupt handler. 323 | * @return error code or 0 if successful. 324 | */ 325 | uint8_t max3421e_poll(void) 326 | { 327 | uint8_t rcode = 0; 328 | 329 | // Check interrupt. 330 | if (MAX_INT() == 0) 331 | rcode = max3421e_interruptHandler(); 332 | 333 | if (MAX_GPX() == 0) 334 | max3421e_gpxInterruptHandler(); 335 | 336 | return (rcode); 337 | } 338 | 339 | /** 340 | * Interrupt handler. 341 | */ 342 | uint8_t max3421e_interruptHandler(void) 343 | { 344 | uint8_t interruptStatus; 345 | uint8_t HIRQ_sendback = 0x00; 346 | 347 | // Determine interrupt source. 348 | interruptStatus = max3421e_read(MAX_REG_HIRQ); 349 | 350 | if (interruptStatus & bmFRAMEIRQ) 351 | { 352 | //->1ms SOF interrupt handler 353 | HIRQ_sendback |= bmFRAMEIRQ; 354 | } 355 | 356 | if (interruptStatus & bmCONDETIRQ) 357 | { 358 | max3421e_busprobe(); 359 | 360 | HIRQ_sendback |= bmCONDETIRQ; 361 | } 362 | 363 | // End HIRQ interrupts handling, clear serviced IRQs 364 | max3421e_write(MAX_REG_HIRQ, HIRQ_sendback); 365 | 366 | return (HIRQ_sendback); 367 | } 368 | 369 | /** 370 | * GPX interrupt handler 371 | */ 372 | uint8_t max3421e_gpxInterruptHandler(void) 373 | { 374 | //read GPIN IRQ register 375 | uint8_t interruptStatus = max3421e_read(MAX_REG_GPINIRQ); 376 | 377 | // if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload 378 | // vbusPwr( OFF ); //attempt powercycle 379 | // delay( 1000 ); 380 | // vbusPwr( ON ); 381 | // regWr( rGPINIRQ, bmGPINIRQ7 ); 382 | // } 383 | 384 | return (interruptStatus); 385 | } 386 | 387 | -------------------------------------------------------------------------------- /max3421e.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Niels Brouwers 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License.#include 15 | */ 16 | 17 | /** 18 | * 19 | * Library for the max3421e USB host controller shield produced by circuitsathome and Sparkfun. 20 | * This is a low-level interface that provides access to the internal registers and polls the 21 | * controller for state changes. 22 | * 23 | * This library is based on work done by Oleg Mazurov, but has been heavily restructured. 24 | * 25 | * Control over the GPIO pins has been stripped. 26 | * 27 | * http://www.circuitsathome.com/ 28 | */ 29 | #ifndef __max3421e_h__ 30 | #define __max3421e_h__ 31 | 32 | #include "max3421e_constants.h" 33 | #include "pins_arduino.h" 34 | 35 | /** 36 | * Max3421e registers in host mode. 37 | */ 38 | typedef enum 39 | { 40 | MAX_REG_RCVFIFO = 0x08, 41 | MAX_REG_SNDFIFO = 0x10, 42 | MAX_REG_SUDFIFO = 0x20, 43 | MAX_REG_RCVBC = 0x30, 44 | MAX_REG_SNDBC = 0x38, 45 | MAX_REG_USBIRQ = 0x68, 46 | MAX_REG_USBIEN = 0x70, 47 | MAX_REG_CPUCTL = 0x80, 48 | MAX_REG_USBCTL = 0x78, 49 | MAX_REG_PINCTL = 0x88, 50 | MAX_REG_REVISION = 0x90, 51 | MAX_REG_FNADDR = 0x98, 52 | MAX_REG_GPINIRQ = 0xb0, 53 | MAX_REG_HIRQ = 0xc8, 54 | MAX_REG_HIEN = 0xd0, 55 | MAX_REG_MODE = 0xd8, 56 | MAX_REG_PERADDR = 0xe0, 57 | MAX_REG_HCTL = 0xe8, 58 | MAX_REG_HXFR = 0xf0, 59 | MAX_REG_HRSL = 0xf8 60 | } max_registers; 61 | 62 | /* 63 | #define PIN_MAX_SS 10 64 | #define PIN_MAX_INT 9 65 | #define PIN_MAX_GPX 8 66 | #define PIN_MAX_RESET 7 67 | 68 | #define MAX_SS(x) digitalWrite(SS, x) 69 | #define MAX_INT() digitalRead(PIN_MAX_INT) 70 | #define MAX_GPX() digitalRead(PIN_MAX_INT) 71 | #define MAX_RESET(x) digitalWrite(PIN_MAX_RESET, x) 72 | */ 73 | 74 | #define ADK_REF_BOARD 75 | 76 | // Completely untested guesswork for the ADK reference board 77 | 78 | 79 | #define PIN_MAX_SS 53 80 | #define PIN_MAX_INT 9 81 | #define PIN_MAX_GPX 8 82 | #define PIN_MAX_RESET 7 83 | 84 | #define MAX_SS(x) digitalWrite(SS, x) 85 | #define MAX_INT() ((PORTE & 0x40) >> 6) 86 | #define MAX_GPX() ((PORTJ & 0x08) >> 3) 87 | #define MAX_RESET(x) { if (x) PORTJ |= 0x04; else PORTJ &= ~0x04; } 88 | 89 | 90 | 91 | void max3421e_init(); 92 | void max3421e_write(uint8_t reg, uint8_t val); 93 | uint8_t * max3421e_writeMultiple(uint8_t reg, uint8_t count, uint8_t * values); 94 | void max3421e_gpioWr(uint8_t val); 95 | uint8_t max3421e_read(uint8_t reg); 96 | uint8_t * max3421e_readMultiple(uint8_t reg, uint8_t count, uint8_t * values); 97 | uint8_t max3421e_gpioRd(void); 98 | boolean max3421e_reset(); 99 | boolean max3421e_vbusPwr(boolean action); 100 | void max3421e_busprobe(void); 101 | void max3421e_powerOn(); 102 | uint8_t max3421e_getVbusState(); 103 | 104 | uint8_t max3421e_poll(void); 105 | 106 | uint8_t max3421e_interruptHandler(void); 107 | uint8_t max3421e_gpxInterruptHandler(void); 108 | 109 | #endif //_MAX3421E_H_ 110 | -------------------------------------------------------------------------------- /max3421e_constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Niels Brouwers 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License.#include 15 | */ 16 | 17 | /* MAX3421E register/bit names and bitmasks */ 18 | 19 | #ifndef _MAX3421Econstants_h_ 20 | #define _MAX3421Econstants_h_ 21 | 22 | // VBUS states 23 | #define SE0 0 24 | #define SE1 1 25 | #define FSHOST 2 26 | #define LSHOST 3 27 | 28 | /* USBIRQ Bits */ 29 | #define bmVBUSIRQ 0x40 //b6 30 | #define bmNOVBUSIRQ 0x20 //b5 31 | #define bmOSCOKIRQ 0x01 //b0 32 | 33 | /* USBIEN Bits */ 34 | #define bmVBUSIE 0x40 //b6 35 | #define bmNOVBUSIE 0x20 //b5 36 | #define bmOSCOKIE 0x01 //b0 37 | 38 | /* USBCTL Bits */ 39 | #define bmCHIPRES 0x20 //b5 40 | #define bmPWRDOWN 0x10 //b4 41 | 42 | /* CPUCTL Bits */ 43 | #define bmPUSLEWID1 0x80 //b7 44 | #define bmPULSEWID0 0x40 //b6 45 | #define bmIE 0x01 //b0 46 | 47 | /* PINCTL Bits */ 48 | #define bmFDUPSPI 0x10 //b4 49 | #define bmINTLEVEL 0x08 //b3 50 | #define bmPOSINT 0x04 //b2 51 | #define bmGPXB 0x02 //b1 52 | #define bmGPXA 0x01 //b0 53 | 54 | // GPX pin selections 55 | #define GPX_OPERATE 0x00 56 | #define GPX_VBDET 0x01 57 | #define GPX_BUSACT 0x02 58 | #define GPX_SOF 0x03 59 | 60 | /* HIRQ Bits */ 61 | #define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume 62 | #define bmRWUIRQ 0x02 63 | #define bmRCVDAVIRQ 0x04 64 | #define bmSNDBAVIRQ 0x08 65 | #define bmSUSDNIRQ 0x10 66 | #define bmCONDETIRQ 0x20 67 | #define bmFRAMEIRQ 0x40 68 | #define bmHXFRDNIRQ 0x80 69 | 70 | /* HIEN Bits */ 71 | #define bmBUSEVENTIE 0x01 72 | #define bmRWUIE 0x02 73 | #define bmRCVDAVIE 0x04 74 | #define bmSNDBAVIE 0x08 75 | #define bmSUSDNIE 0x10 76 | #define bmCONDETIE 0x20 77 | #define bmFRAMEIE 0x40 78 | #define bmHXFRDNIE 0x80 79 | 80 | /* MODE Bits */ 81 | #define bmHOST 0x01 82 | #define bmLOWSPEED 0x02 83 | #define bmHUBPRE 0x04 84 | #define bmSOFKAENAB 0x08 85 | #define bmSEPIRQ 0x10 86 | #define bmDELAYISO 0x20 87 | #define bmDMPULLDN 0x40 88 | #define bmDPPULLDN 0x80 89 | 90 | /* HCTL Bits */ 91 | #define bmBUSRST 0x01 92 | #define bmFRMRST 0x02 93 | #define bmSAMPLEBUS 0x04 94 | #define bmSIGRSM 0x08 95 | #define bmRCVTOG0 0x10 96 | #define bmRCVTOG1 0x20 97 | #define bmSNDTOG0 0x40 98 | #define bmSNDTOG1 0x80 99 | 100 | /* Host transfer token values for writing the HXFR register (R30) */ 101 | /* OR this bit field with the endpoint number in bits 3:0 */ 102 | #define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1 103 | #define tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0 104 | #define tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0 105 | #define tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0 106 | #define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0 107 | #define tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0 108 | #define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0 109 | 110 | /* HRSL Bits */ 111 | #define bmRCVTOGRD 0x10 112 | #define bmSNDTOGRD 0x20 113 | #define bmKSTATUS 0x40 114 | #define bmJSTATUS 0x80 115 | #define bmSE0 0x00 //SE0 - disconnect state 116 | #define bmSE1 0xc0 //SE1 - illegal state 117 | 118 | /* Host error result codes, the 4 LSB's in the HRSL register */ 119 | #define hrSUCCESS 0x00 120 | #define hrBUSY 0x01 121 | #define hrBADREQ 0x02 122 | #define hrUNDEF 0x03 123 | #define hrNAK 0x04 124 | #define hrSTALL 0x05 125 | #define hrTOGERR 0x06 126 | #define hrWRONGPID 0x07 127 | #define hrBADBC 0x08 128 | #define hrPIDERR 0x09 129 | #define hrPKTERR 0x0A 130 | #define hrCRCERR 0x0B 131 | #define hrKERR 0x0C 132 | #define hrJERR 0x0D 133 | #define hrTIMEOUT 0x0E 134 | #define hrBABBLE 0x0F 135 | 136 | #define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB) 137 | #define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB) 138 | 139 | #endif //_MAX3421Econstants_h_ 140 | -------------------------------------------------------------------------------- /usb.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011 Niels Brouwers 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License.#include 15 | */ 16 | 17 | #include 18 | #include "usb.h" 19 | #include "ch9.h" 20 | #include "max3421e.h" 21 | #include "HardwareSerial.h" 22 | 23 | #include 24 | 25 | static uint8_t usb_error = 0; 26 | static uint8_t usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; 27 | static usb_eventHandler * eventHandler = NULL; 28 | 29 | usb_device deviceTable[USB_NUMDEVICES + 1]; 30 | 31 | /** 32 | * Initialises the USB layer. 33 | */ 34 | void USB::init() 35 | { 36 | max3421e_init(); 37 | max3421e_powerOn(); 38 | 39 | uint8_t i; 40 | 41 | // Initialise the USB state machine. 42 | usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; 43 | 44 | // Initialise the device table. 45 | for (i = 0; i < (USB_NUMDEVICES + 1); i++) 46 | deviceTable[i].active = false; 47 | 48 | // Address 0 is used to configure devices and assign them an address when they are first plugged in 49 | deviceTable[0].address = 0; 50 | USB::initEndPoint(&(deviceTable[0].control), 0); 51 | 52 | } 53 | 54 | /** 55 | * Initialises a USB endpoint. 56 | * @param endpoint USB endpoint 57 | * @param address endpoint address 58 | */ 59 | void USB::initEndPoint(usb_endpoint * endpoint, uint8_t address) 60 | { 61 | endpoint->address = address; 62 | endpoint->sendToggle = bmSNDTOG0; 63 | endpoint->receiveToggle = bmRCVTOG0; 64 | } 65 | 66 | /** 67 | * Initialises a USB device and switches to the given configuration 68 | * @param USB device 69 | * @param configuration configuration to switch to 70 | * @return negative error code or zero on success. 71 | */ 72 | int USB::initDevice(usb_device * device, int configuration) 73 | { 74 | char buf[4]; 75 | 76 | uint8_t rcode; 77 | 78 | // Set the configuration for this USB device. 79 | rcode = USB::setConfiguration(device, configuration); 80 | if (rcode<0) return rcode; 81 | 82 | // Get the first supported language. 83 | rcode = USB::getString(device, 0, 0, 4, buf); 84 | if (rcode<0) return rcode; 85 | device->firstStringLanguage = (buf[3] << 8) | buf[2]; 86 | 87 | return rcode; 88 | } 89 | 90 | /** 91 | * Sets the global USB event callback function. Use this to catch global events like device connect/disconnect. 92 | * @param handler event handler function. 93 | */ 94 | void USB::setEventHandler(usb_eventHandler * handler) 95 | { 96 | eventHandler = handler; 97 | } 98 | 99 | /** 100 | * Fires a USB event. This calls the callback function set by setEventHandler. 101 | * 102 | * @param device the device the events relates to. 103 | * @param event event type (i.e. connected, disconnected) 104 | */ 105 | void USB::fireEvent(usb_device * device, usb_eventType event) 106 | { 107 | eventHandler(device, event); 108 | } 109 | 110 | // private 111 | uint8_t usb_getUsbTaskState() 112 | { 113 | return (usb_task_state); 114 | } 115 | 116 | // private 117 | void usb_setUsbTaskState(uint8_t state) 118 | { 119 | usb_task_state = state; 120 | } 121 | 122 | /** 123 | * Gets the usb device at the given address, or NULL is the address is out of range (greater than USB_NUMDEVICES+1, 124 | * as address zero is reserver). 125 | * @param address USB device address 126 | * @return USB device struct or NULL on failure (address out of range) 127 | */ 128 | usb_device * usb_getDevice(uint8_t address) 129 | { 130 | if (address>USB_NUMDEVICES+1) return NULL; 131 | 132 | return &(deviceTable[address]); 133 | } 134 | 135 | int usb_dispatchPacket(uint8_t token, usb_endpoint * endpoint, unsigned int nakLimit) 136 | { 137 | uint32_t timeout = millis() + USB_XFER_TIMEOUT; 138 | uint8_t tmpdata; 139 | uint8_t rcode = 0; 140 | unsigned int nak_count = 0; 141 | char retry_count = 0; 142 | 143 | while (timeout > millis()) 144 | { 145 | // Analyze transfer result. 146 | 147 | // Launch the transfer. 148 | max3421e_write(MAX_REG_HXFR, (token | endpoint->address)); 149 | rcode = 0xff; 150 | 151 | // Wait for interrupt 152 | while (timeout > millis()) 153 | { 154 | tmpdata = max3421e_read(MAX_REG_HIRQ); 155 | if (tmpdata & bmHXFRDNIRQ) 156 | { 157 | // Clear the interrupt. 158 | max3421e_write(MAX_REG_HIRQ, bmHXFRDNIRQ); 159 | 160 | rcode = 0x00; 161 | break; 162 | } 163 | } 164 | 165 | // Exit if timeout. 166 | if (rcode != 0x00) 167 | return (rcode); 168 | 169 | // Wait for HRSL 170 | while (timeout > millis()) 171 | { 172 | rcode = (max3421e_read(MAX_REG_HRSL) & 0x0f); 173 | if (rcode != hrBUSY) 174 | break; 175 | // else 176 | // serialPrintf("busy!\n"); 177 | } 178 | 179 | 180 | switch (rcode) 181 | { 182 | case hrNAK: 183 | nak_count++; 184 | if (nak_count == nakLimit) 185 | return (rcode); 186 | break; 187 | case hrTIMEOUT: 188 | retry_count++; 189 | if (retry_count == USB_RETRY_LIMIT) 190 | return (rcode); 191 | break; 192 | default: 193 | return (rcode); 194 | } 195 | } 196 | 197 | return (rcode); 198 | } 199 | 200 | /** 201 | * USB poll method. Performs enumeration/cleanup. 202 | */ 203 | void USB::poll() 204 | { 205 | uint8_t i; 206 | uint8_t rcode; 207 | uint8_t tmpdata; 208 | static unsigned long delay = 0; 209 | usb_deviceDescriptor deviceDescriptor; 210 | 211 | // Poll the MAX3421E device. 212 | max3421e_poll(); 213 | 214 | /* modify USB task state if Vbus changed */ 215 | tmpdata = max3421e_getVbusState(); 216 | 217 | switch (tmpdata) 218 | { 219 | case SE1: //illegal state 220 | usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; 221 | break; 222 | case SE0: //disconnected 223 | if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED) 224 | { 225 | usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; 226 | } 227 | break; 228 | case FSHOST: //attached 229 | case LSHOST: 230 | if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) 231 | { 232 | delay = millis() + USB_SETTLE_DELAY; 233 | usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; 234 | } 235 | break; 236 | }// switch( tmpdata 237 | 238 | //Serial.print("USB task state: "); 239 | //Serial.println( usb_task_state, HEX ); 240 | 241 | switch (usb_task_state) 242 | { 243 | case USB_DETACHED_SUBSTATE_INITIALIZE: 244 | 245 | // TODO right now it looks like the USB board is just reset on disconnect. Fire disconnect for all connected 246 | // devices. 247 | for (i = 1; i < USB_NUMDEVICES; i++) 248 | if (deviceTable[i].active) 249 | USB::fireEvent(&(deviceTable[i]), USB_DISCONNECT); 250 | 251 | USB::init(); 252 | usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; 253 | break; 254 | case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here 255 | break; 256 | case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here 257 | break; 258 | case USB_ATTACHED_SUBSTATE_SETTLE: //setlle time for just attached device 259 | if (delay < millis()) 260 | { 261 | usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; 262 | } 263 | break; 264 | 265 | case USB_ATTACHED_SUBSTATE_RESET_DEVICE: 266 | // Issue bus reset. 267 | max3421e_write(MAX_REG_HCTL, bmBUSRST); 268 | usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE; 269 | break; 270 | 271 | case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: 272 | if ((max3421e_read(MAX_REG_HCTL) & bmBUSRST) == 0) 273 | { 274 | tmpdata = max3421e_read(MAX_REG_MODE) | bmSOFKAENAB; //start SOF generation 275 | max3421e_write(MAX_REG_MODE, tmpdata); 276 | // max3421e_regWr( rMODE, bmSOFKAENAB ); 277 | usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF; 278 | delay = millis() + 20; //20ms wait after reset per USB spec 279 | } 280 | break; 281 | 282 | case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order 283 | if (max3421e_read(MAX_REG_HIRQ) & bmFRAMEIRQ) 284 | { //when first SOF received we can continue 285 | if (delay < millis()) 286 | { //20ms passed 287 | usb_task_state 288 | = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE; 289 | } 290 | } 291 | break; 292 | 293 | case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE: 294 | // toggle( BPNT_0 ); 295 | 296 | deviceTable[0].control.maxPacketSize = 8; 297 | 298 | rcode = USB::getDeviceDescriptor(&deviceTable[0], &deviceDescriptor); 299 | if (rcode == 0) 300 | { 301 | deviceTable[0].control.maxPacketSize = deviceDescriptor.bMaxPacketSize0; 302 | usb_task_state = USB_STATE_ADDRESSING; 303 | } else 304 | { 305 | usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE; 306 | usb_task_state = USB_STATE_ERROR; 307 | } 308 | break; 309 | 310 | case USB_STATE_ADDRESSING: 311 | 312 | // Look for an empty spot 313 | for (i = 1; i < USB_NUMDEVICES; i++) 314 | { 315 | if (!deviceTable[i].active) 316 | { 317 | // Set correct MaxPktSize 318 | // deviceTable[i].epinfo = deviceTable[0].epinfo; 319 | 320 | deviceTable[i].address = i; 321 | deviceTable[i].active = true; 322 | 323 | USB::initEndPoint(&(deviceTable[i].control), 0); 324 | 325 | // temporary record until plugged with real device endpoint structure 326 | rcode = USB::setAddress(&deviceTable[0], i); 327 | 328 | if (rcode == 0) 329 | { 330 | USB::fireEvent(&deviceTable[i], USB_CONNECT); 331 | // usb_task_state = USB_STATE_CONFIGURING; 332 | // NB: I've bypassed the configuring state, because configuration should be handled 333 | // in the usb event handler. 334 | usb_task_state = USB_STATE_RUNNING; 335 | } else 336 | { 337 | USB::fireEvent(&deviceTable[i], USB_ADRESSING_ERROR); 338 | 339 | // TODO remove usb_error at some point? 340 | usb_error = USB_STATE_ADDRESSING; 341 | usb_task_state = USB_STATE_ERROR; 342 | } 343 | break; //break if address assigned or error occured during address assignment attempt 344 | } 345 | } 346 | 347 | // If no vacant spot was found in the device table, fire an error. 348 | if (usb_task_state == USB_STATE_ADDRESSING) 349 | { 350 | USB::fireEvent(&deviceTable[i], USB_ADRESSING_ERROR); 351 | 352 | // No vacant place in devtable 353 | usb_error = 0xfe; 354 | usb_task_state = USB_STATE_ERROR; 355 | } 356 | 357 | break; 358 | case USB_STATE_CONFIGURING: 359 | break; 360 | case USB_STATE_RUNNING: 361 | break; 362 | case USB_STATE_ERROR: 363 | break; 364 | } 365 | } 366 | 367 | /** 368 | * Convenience method for getting a string. This is useful for printing manufacturer names, serial numbers, etc. 369 | * Language is defaulted to zero. Strings are returned in 16-bit unicode from the device, so this function converts the 370 | * result to ASCII by ignoring every second byte. However, since the target buffer is used as a temporary storage during 371 | * this process it must be twice as large as the desired maximum string size. 372 | * 373 | * @param device USB device. 374 | * @param index string index. 375 | * @param languageId language ID. 376 | * @param length buffer length. 377 | * @param str target buffer. 378 | * @return 0 on success, error code otherwise. 379 | */ 380 | int USB::getString(usb_device * device, uint8_t index, uint8_t languageId, uint16_t length, char * str) 381 | { 382 | uint8_t stringLength = 0; 383 | int i, ret = 0; 384 | 385 | // Get string length; 386 | ret = USB::controlRequest(device, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, languageId, sizeof(uint8_t), &stringLength); 387 | if (ret<0) return -1; 388 | 389 | // Trim string size to fit the target buffer. 390 | if (stringLength>length) stringLength = length; 391 | 392 | // Get the whole thing. 393 | ret = USB::controlRequest(device, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, languageId, stringLength, (uint8_t *)str); 394 | if (ret<0) return -2; 395 | 396 | // Convert to 8-bit ASCII 397 | stringLength = (stringLength - 2) / 2; 398 | for (i=0; imaxPacketSize; 416 | 417 | unsigned int totalTransferred = 0; 418 | 419 | // Set device address. 420 | max3421e_write(MAX_REG_PERADDR, device->address); 421 | 422 | // Set toggle value. 423 | max3421e_write(MAX_REG_HCTL, endpoint->receiveToggle); 424 | 425 | while (1) 426 | { 427 | 428 | // Start IN transfer 429 | rcode = usb_dispatchPacket(tokIN, endpoint, nakLimit); 430 | 431 | if (rcode) 432 | { 433 | // if (rcode != hrNAK) 434 | // serialPrintf("USB::read: dispatch error %d\n", rcode); 435 | 436 | return -1; 437 | } 438 | 439 | // Assert that the RCVDAVIRQ bit in register MAX_REG_HIRQ is set. 440 | if ((max3421e_read(MAX_REG_HIRQ) & bmRCVDAVIRQ) == 0) 441 | { 442 | // serialPrintf("USB::read: toggle error? %d\n", rcode); 443 | 444 | // TODO: the absence of RCVDAVIRQ indicates a toggle error. Need to add handling for that. 445 | return -2; 446 | } 447 | 448 | // Obtain the number of bytes in FIFO. 449 | bytesRead = max3421e_read(MAX_REG_RCVBC); 450 | 451 | // Read the data from the FIFO. 452 | data = max3421e_readMultiple(MAX_REG_RCVFIFO, bytesRead, data); 453 | 454 | // Clear the interrupt to free the buffer. 455 | max3421e_write(MAX_REG_HIRQ, bmRCVDAVIRQ); 456 | 457 | totalTransferred += bytesRead; 458 | 459 | // Check if we're done reading. Either we've received a 'short' packet (= length)) 462 | { 463 | // Remember the toggle value for the next transfer. 464 | if (max3421e_read(MAX_REG_HRSL) & bmRCVTOGRD) 465 | endpoint->receiveToggle = bmRCVTOG1; 466 | else 467 | endpoint->receiveToggle = bmRCVTOG0; 468 | 469 | // Break out of the loop. 470 | break; 471 | } 472 | } 473 | 474 | // Report success. 475 | return totalTransferred; 476 | } 477 | 478 | 479 | /** 480 | * Performs a bulk in transfer from a USB device. 481 | * 482 | * @param device USB bulk device. 483 | * @param device length number of bytes to read. 484 | * @param data target buffer. 485 | * 486 | * @return number of bytes read, or error code in case of failure. 487 | */ 488 | int USB::bulkRead(usb_device * device, uint16_t length, uint8_t * data, boolean poll) 489 | { 490 | return USB::read(device, &(device->bulk_in), length, data, poll ? 1 : USB_NAK_LIMIT); 491 | } 492 | 493 | 494 | /** 495 | * Performs ab out transfer to a USB device on an arbitrary endpoint. 496 | * 497 | * @param device USB bulk device. 498 | * @param device length number of bytes to read. 499 | * @param data target buffer. 500 | * @return number of bytes written, or error code in case of failure. 501 | */ 502 | int USB::write(usb_device * device, usb_endpoint * endpoint, uint16_t length, uint8_t * data) 503 | { 504 | uint8_t rcode = 0, retry_count; 505 | 506 | // Set device address. 507 | max3421e_write(MAX_REG_PERADDR, device->address); 508 | 509 | // Local copy of the data pointer. 510 | uint8_t * data_p = data; 511 | 512 | unsigned int bytes_tosend, nak_count; 513 | unsigned int bytes_left = length; 514 | unsigned int nak_limit = USB_NAK_LIMIT; 515 | 516 | uint32_t timeout = millis() + USB_XFER_TIMEOUT; 517 | 518 | uint8_t maxPacketSize = endpoint->maxPacketSize; 519 | 520 | // If maximum packet size is not set, return. 521 | if (!maxPacketSize) return 0xFE; 522 | 523 | max3421e_write(MAX_REG_HCTL, endpoint->sendToggle); //set toggle value 524 | 525 | while (bytes_left) 526 | { 527 | retry_count = 0; 528 | nak_count = 0; 529 | 530 | bytes_tosend = (bytes_left >= maxPacketSize) ? maxPacketSize : bytes_left; 531 | 532 | // Filling output FIFO 533 | max3421e_writeMultiple(MAX_REG_SNDFIFO, bytes_tosend, data_p); 534 | 535 | // Set number of bytes to send. 536 | max3421e_write(MAX_REG_SNDBC, bytes_tosend); 537 | 538 | // Dispatch packet. 539 | max3421e_write(MAX_REG_HXFR, (tokOUT | endpoint->address)); 540 | 541 | // Wait for completion. 542 | while (!(max3421e_read(MAX_REG_HIRQ) & bmHXFRDNIRQ)); 543 | 544 | // Clear IRQ. 545 | max3421e_write(MAX_REG_HIRQ, bmHXFRDNIRQ); 546 | 547 | rcode = (max3421e_read(MAX_REG_HRSL) & 0x0f); 548 | 549 | while (rcode && (timeout > millis())) 550 | { 551 | switch (rcode) 552 | { 553 | case hrNAK: 554 | nak_count++; 555 | if (nak_limit && (nak_count == USB_NAK_LIMIT)) 556 | { 557 | return (rcode); //return NAK 558 | } 559 | break; 560 | case hrTIMEOUT: 561 | retry_count++; 562 | if (retry_count == USB_RETRY_LIMIT) 563 | { 564 | return (rcode); //return TIMEOUT 565 | } 566 | break; 567 | default: 568 | return (rcode); 569 | } 570 | 571 | // Process NAK according to Host out NAK bug. 572 | max3421e_write(MAX_REG_SNDBC, 0); 573 | max3421e_write(MAX_REG_SNDFIFO, *data_p); 574 | max3421e_write(MAX_REG_SNDBC, bytes_tosend); 575 | max3421e_write(MAX_REG_HXFR, (tokOUT | endpoint->address)); //dispatch packet 576 | 577 | // Wait for the completion interrupt. 578 | while (!(max3421e_read(MAX_REG_HIRQ) & bmHXFRDNIRQ)); 579 | 580 | // Clear interrupt. 581 | max3421e_write(MAX_REG_HIRQ, bmHXFRDNIRQ); 582 | 583 | rcode = (max3421e_read(MAX_REG_HRSL) & 0x0f); 584 | } 585 | 586 | bytes_left -= bytes_tosend; 587 | data_p += bytes_tosend; 588 | } 589 | 590 | endpoint->sendToggle = (max3421e_read(MAX_REG_HRSL) & bmSNDTOGRD) ? bmSNDTOG1 : bmSNDTOG0; //update toggle 591 | 592 | // Should be 0 in all cases. 593 | return (rcode); 594 | } 595 | 596 | /** 597 | * Performs a bulk out transfer to a USB device. 598 | * 599 | * @param device USB bulk device. 600 | * @param device length number of bytes to read. 601 | * @param data target buffer. 602 | * @return number of bytes read, or error code in case of failure. 603 | */ 604 | int USB::bulkWrite(usb_device * device, uint16_t length, uint8_t * data) 605 | { 606 | return USB::write(device, &(device->bulk_out) , length, data); 607 | } 608 | 609 | /** 610 | * Read/write data to/from the control endpoint of a device. 611 | * 612 | * @param device USB device. 613 | * @param direction true for input, false for output. 614 | * @param length number of bytes to transfer. 615 | * @param data data buffer. 616 | */ 617 | uint8_t USB::ctrlData(usb_device * device, boolean direction, uint16_t length, uint8_t * data) 618 | { 619 | if (direction) 620 | { 621 | // IN transfer 622 | device->control.receiveToggle = bmRCVTOG1; 623 | return USB::read(device, &(device->control), length, data, USB_NAK_LIMIT); 624 | 625 | } else 626 | { 627 | // OUT transfer 628 | device->control.sendToggle = bmSNDTOG1; 629 | return USB::write(device, &(device->control), length, data); 630 | } 631 | } 632 | 633 | /** 634 | * Sends a control request to a USB device. 635 | * 636 | * @param device USB device to send the control request to. 637 | * @param requestType request type (in/out). 638 | * @param request request. 639 | * @param valueLow low byte of the value parameter. 640 | * @param valueHigh high byte of the value parameter. 641 | * @param index index. 642 | * @param length number of bytes to transfer. 643 | * @param data data to send in case of output transfer, or reception buffer in case of input. If no data is to be exchanged this should be set to NULL. 644 | * @return 0 on success, error code otherwise 645 | */ 646 | int USB::controlRequest( 647 | usb_device * device, 648 | uint8_t requestType, 649 | uint8_t request, 650 | uint8_t valueLow, 651 | uint8_t valueHigh, 652 | uint16_t index, 653 | uint16_t length, 654 | uint8_t * data) 655 | { 656 | boolean direction = false; //request direction, IN or OUT 657 | uint8_t rcode; 658 | usb_setupPacket setup_pkt; 659 | 660 | // Set device address. 661 | max3421e_write(MAX_REG_PERADDR, device->address); 662 | 663 | if (requestType & 0x80) 664 | direction = true; //determine request direction 665 | 666 | // Build setup packet. 667 | setup_pkt.bmRequestType = requestType; 668 | setup_pkt.bRequest = request; 669 | setup_pkt.wValue = valueLow | (valueHigh << 8); 670 | setup_pkt.wIndex = index; 671 | setup_pkt.wLength = length; 672 | 673 | // Write setup packet to the FIFO and dispatch 674 | max3421e_writeMultiple(MAX_REG_SUDFIFO, 8, (uint8_t *) &setup_pkt); 675 | rcode = usb_dispatchPacket(tokSETUP, &(device->control), USB_NAK_LIMIT); 676 | 677 | // Print error in case of failure. 678 | if (rcode) 679 | { 680 | // serialPrintf("Setup packet error: 0x%02x\n", rcode); 681 | return -1; 682 | } 683 | 684 | // Data stage, if present 685 | if (data != NULL) 686 | { 687 | rcode = USB::ctrlData(device, direction, length, data); 688 | 689 | // If unsuccessful, return error. 690 | if (rcode<0) 691 | { 692 | // serialPrintf("Data packet error: 0x%02x\n", rcode); 693 | return -2; 694 | } 695 | } 696 | 697 | // Status stage. 698 | if (direction) 699 | rcode = usb_dispatchPacket(tokOUTHS, &(device->control), USB_NAK_LIMIT); 700 | else 701 | rcode = usb_dispatchPacket(tokINHS, &(device->control), USB_NAK_LIMIT); 702 | 703 | if (rcode) 704 | return -3; 705 | else 706 | return 0; 707 | } 708 | 709 | /** 710 | * Gets the device descriptor of a USB device. 711 | * @param device USB device 712 | * @param descriptor pointer to a usb_deviceDescriptor record that will be filled with the requested data. 713 | * @return 0 in case of success, error code otherwise 714 | */ 715 | int USB::getDeviceDescriptor(usb_device * device, usb_deviceDescriptor * descriptor) 716 | { 717 | return(USB::controlRequest(device, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, sizeof(usb_deviceDescriptor), (uint8_t *)descriptor)); 718 | } 719 | 720 | /** 721 | * Gets the configuration descriptor of a USB device as a byte array. 722 | * @param device USB device 723 | * @param conf configuration number 724 | * @param length length of the data buffer. This method will not write beyond this boundary. 725 | * @return number of bytes read, or negative number in case of error. 726 | */ 727 | int USB::getConfigurationDescriptor(usb_device * device, uint8_t conf, uint16_t length, uint8_t * data) 728 | { 729 | uint16_t descriptorLength; 730 | int rcode; 731 | 732 | // Read the length of the configuration descriptor. 733 | rcode = (USB::controlRequest(device, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, 4, data)); 734 | if (rcode) return -1; 735 | 736 | descriptorLength = (data[3] << 8) | data[2]; 737 | if (descriptorLength 15 | */ 16 | 17 | #ifndef __usb__ 18 | #define __usb__ 19 | 20 | #include 21 | #include 22 | 23 | // Device descriptor. 24 | typedef struct 25 | { 26 | uint8_t bLength; // Length of this descriptor. 27 | uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). 28 | uint16_t bcdUSB; // USB Spec Release Number (BCD). 29 | uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. 30 | uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). 31 | uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. 32 | uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. 33 | uint16_t idVendor; // Vendor ID (assigned by the USB-IF). 34 | uint16_t idProduct; // Product ID (assigned by the manufacturer). 35 | uint16_t bcdDevice; // Device release number (BCD). 36 | uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. 37 | uint8_t iProduct; // Index of String Descriptor describing the product. 38 | uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. 39 | uint8_t bNumConfigurations; // Number of possible configurations. 40 | } usb_deviceDescriptor; 41 | 42 | // Configuration descriptor. 43 | typedef struct 44 | { 45 | uint8_t bLength; // Length of this descriptor. 46 | uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). 47 | uint16_t wTotalLength; // Total length of all descriptors for this configuration. 48 | uint8_t bNumInterfaces; // Number of interfaces in this configuration. 49 | uint8_t bConfigurationValue; // Value of this configuration (1 based). 50 | uint8_t iConfiguration; // Index of String Descriptor describing the configuration. 51 | uint8_t bmAttributes; // Configuration characteristics. 52 | uint8_t bMaxPower; // Maximum power consumed by this configuration. 53 | } usb_configurationDescriptor; 54 | 55 | // Interface descriptor. 56 | typedef struct 57 | { 58 | uint8_t bLength; // Length of this descriptor. 59 | uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). 60 | uint8_t bInterfaceNumber; // Number of this interface (0 based). 61 | uint8_t bAlternateSetting; // Value of this alternate interface setting. 62 | uint8_t bNumEndpoints; // Number of endpoints in this interface. 63 | uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. 64 | uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF). 65 | uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. 66 | uint8_t iInterface; // Index of String Descriptor describing the interface. 67 | } usb_interfaceDescriptor; 68 | 69 | /* Endpoint descriptor structure */ 70 | typedef struct 71 | { 72 | uint8_t bLength; // Length of this descriptor. 73 | uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). 74 | uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). 75 | uint8_t bmAttributes; // Endpoint transfer type. 76 | uint16_t wMaxPacketSize; // Maximum packet size. 77 | uint8_t bInterval; // Polling interval in frames. 78 | } usb_endpointDescriptor; 79 | 80 | // USB Setup Packet. 81 | typedef struct 82 | { 83 | uint8_t bmRequestType; // 0 Bit-map of request type 84 | uint8_t bRequest; // 1 Request 85 | uint16_t wValue; // 2 Depends on bRequest 86 | uint16_t wIndex; // 4 Depends on bRequest 87 | uint16_t wLength; // 6 Depends on bRequest 88 | } usb_setupPacket; 89 | 90 | /** 91 | * USB endpoint. 92 | */ 93 | typedef struct 94 | { 95 | // Endpoint address. Bit 7 indicates direction (out=0, in=1). 96 | uint8_t address; 97 | 98 | // Endpoint transfer type. 99 | uint8_t attributes; 100 | 101 | // Maximum packet size. 102 | uint16_t maxPacketSize; 103 | 104 | // The max3421e uses these bits to toggle between DATA0 and DATA1. 105 | uint8_t sendToggle; 106 | uint8_t receiveToggle; 107 | 108 | } usb_endpoint; 109 | 110 | /** 111 | * USB device. 112 | */ 113 | typedef struct 114 | { 115 | // Device address. 116 | uint8_t address; 117 | 118 | // Indicates whether this device is active. 119 | uint8_t active; 120 | 121 | // Endpoints. 122 | usb_endpoint control; 123 | usb_endpoint bulk_in, bulk_out; 124 | 125 | // First supported language (for retrieving Strings) 126 | uint16_t firstStringLanguage; 127 | 128 | } usb_device; 129 | 130 | typedef enum 131 | { 132 | USB_CONNECT, 133 | USB_DISCONNECT, 134 | USB_ADRESSING_ERROR 135 | } usb_eventType; 136 | 137 | /* Common setup data constant combinations */ 138 | #define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type 139 | #define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface' 140 | #define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type 141 | 142 | /* HID requests */ 143 | /* 144 | #define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE 145 | #define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE 146 | #define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE 147 | */ 148 | 149 | #define USB_XFER_TIMEOUT 5000 // USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec 150 | #define USB_NAK_LIMIT 32000 // NAK limit for a transfer. o meand NAKs are not counted 151 | #define USB_RETRY_LIMIT 3 // retry limit for a transfer 152 | #define USB_SETTLE_DELAY 200 // settle delay in milliseconds 153 | #define USB_NAK_NOWAIT 1 // used in Richard's PS2/Wiimote code 154 | 155 | #define USB_NUMDEVICES 2 // Number of USB devices 156 | 157 | /* USB state machine states */ 158 | 159 | #define USB_STATE_MASK 0xf0 160 | 161 | #define USB_STATE_DETACHED 0x10 162 | #define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 163 | #define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 164 | #define USB_DETACHED_SUBSTATE_ILLEGAL 0x13 165 | #define USB_ATTACHED_SUBSTATE_SETTLE 0x20 166 | #define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 167 | #define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40 168 | #define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50 169 | #define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60 170 | #define USB_STATE_ADDRESSING 0x70 171 | #define USB_STATE_CONFIGURING 0x80 172 | #define USB_STATE_RUNNING 0x90 173 | #define USB_STATE_ERROR 0xa0 174 | 175 | // USB Device 176 | typedef struct _usb_deviceRecord 177 | { 178 | usb_endpoint * epinfo; //device endpoint information 179 | uint8_t devclass; //device class 180 | } usb_deviceRecord; 181 | 182 | typedef void(usb_eventHandler)(usb_device * device, usb_eventType event); 183 | 184 | class USB 185 | { 186 | 187 | private: 188 | static void fireEvent(usb_device * device, usb_eventType event); 189 | static int setAddress(usb_device * device, uint8_t address); 190 | static int controlRequest(usb_device * device, uint8_t requestType, uint8_t request, uint8_t valueLow, uint8_t valueHigh, uint16_t index, uint16_t length, uint8_t * data); 191 | static int read(usb_device * device, usb_endpoint * endpoint, uint16_t length, uint8_t * data, unsigned int nakLimit); 192 | static int write(usb_device * device, usb_endpoint * endpoint, uint16_t length, uint8_t * data); 193 | static uint8_t ctrlData(usb_device * device, boolean direction, uint16_t length, uint8_t * data); 194 | 195 | public: 196 | static void init(); 197 | static void poll(); 198 | static void setEventHandler(usb_eventHandler * handler); 199 | 200 | static int initDevice(usb_device * device, int configuration); 201 | static usb_device * getDevice(uint8_t address); 202 | 203 | static int setConfiguration(usb_device * device, uint8_t configuration); 204 | 205 | static int getDeviceDescriptor(usb_device * device, usb_deviceDescriptor * descriptor); 206 | static int getConfigurationDescriptor(usb_device * device, uint8_t conf, uint16_t length, uint8_t * data); 207 | static int getString(usb_device * device, uint8_t index, uint8_t languageId, uint16_t length, char * str); 208 | 209 | static void initEndPoint(usb_endpoint * endpoint, uint8_t address); 210 | 211 | static int bulkRead(usb_device * device, uint16_t length, uint8_t * data, boolean poll); 212 | static int bulkWrite(usb_device * device, uint16_t length, uint8_t * data); 213 | 214 | }; 215 | 216 | #endif 217 | --------------------------------------------------------------------------------