Joe Fernandez | 3a77ccc | 2012-06-24 23:58:25 -0700 | [diff] [blame] | 1 | page.title=Accessory Development Kit 2011 Guide |
Joe Fernandez | 33baa5a | 2013-11-14 11:41:19 -0800 | [diff] [blame] | 2 | page.tags=adk |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 3 | @jd:body |
| 4 | |
| 5 | <div id="qv-wrapper"> |
| 6 | <div id="qv"> |
| 7 | <h2>In this document</h2> |
| 8 | |
| 9 | <ol> |
| 10 | <li><a href="#components">ADK Components</a></li> |
| 11 | <li> |
| 12 | |
| 13 | <a href="#getting-started">Getting Started with the ADK</a> |
| 14 | |
| 15 | <ol> |
| 16 | <li><a href="#installing">Installing the Arduino software and necessary |
| 17 | libraries</a></li> |
| 18 | |
| 19 | <li><a href="#installing-firmware">Installing the firmware to the ADK board</a></li> |
| 20 | |
| 21 | <li><a href="#running-demokit">Running the DemoKit Android application</a></li> |
| 22 | |
| 23 | <li><a href="#monitoring">Monitoring the ADK board</a></li> |
| 24 | </ol> |
| 25 | </li> |
| 26 | |
| 27 | <li> |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 28 | <a href="#firmware">How the ADK board implements the Android Accessory Protocol</a> |
| 29 | |
| 30 | <ol> |
| 31 | <li><a href="#wait-adk">Wait for and detect connected devices</a></li> |
| 32 | |
| 33 | <li><a href="#determine-adk">Determine the connected device's accessory mode |
| 34 | support</a></li> |
| 35 | |
| 36 | <li><a href="#start-adk">Attempt to start the device in accessory mode</a></li> |
| 37 | |
| 38 | <li><a href="#establish-adk">Establish communication with the device</a></li> |
| 39 | </ol> |
| 40 | </li> |
| 41 | </ol> |
| 42 | |
| 43 | <h2>Download</h2> |
| 44 | <ol> |
Scott Main | fe3b1cb | 2012-07-24 18:13:11 -0700 | [diff] [blame] | 45 | <li><a href="https://dl-ssl.google.com/android/adk/adk_release_20120606.zip">ADK package</a></li> |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 46 | </ol> |
| 47 | |
| 48 | <h2>See also</h2> |
| 49 | |
| 50 | <ol> |
| 51 | <li><a href="http://www.youtube.com/watch?v=s7szcpXf2rE">Google I/O Session Video</a></li> |
| 52 | <li><a href="{@docRoot}guide/topics/connectivity/usb/accessory.html">USB Accessory Dev Guide</a></li> |
| 53 | </ol> |
| 54 | |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 55 | </div> |
| 56 | </div> |
| 57 | |
Joe Fernandez | 3a77ccc | 2012-06-24 23:58:25 -0700 | [diff] [blame] | 58 | <p>The Android Open Accessory Development Kit (ADK) is a reference implementation of an Android |
| 59 | Open Accessory, based on the <a href="http://www.arduino.cc/">Arduino open source electronics |
| 60 | prototyping platform</a>. The accessory's hardware design files, code that implements the |
| 61 | accessory's firmware, and the Android application that interacts with the accessory are provided |
| 62 | as part of the kit to help hardware builders and software developers get started building their |
| 63 | own accessories. The hardware design files and firmware code are contained in the <a href= |
| 64 | "https://dl-ssl.google.com/android/adk/adk_release_20120606.zip">ADK package download</a>.</p> |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 65 | |
Joe Fernandez | 3a77ccc | 2012-06-24 23:58:25 -0700 | [diff] [blame] | 66 | <p>A limited number of kits were produced and distributed at the Google I/O 2011 developer |
| 67 | conference. However, many hardware builders have reproduced and enhanced the original design and |
| 68 | these boards are available for purchase. The following list of distributors are currently |
| 69 | producing Android Open Accessory compatible development boards:</p> |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 70 | |
| 71 | <ul> |
Joe Fernandez | 3a77ccc | 2012-06-24 23:58:25 -0700 | [diff] [blame] | 72 | <li>The <a href="http://store.arduino.cc/">Arduino Store</a> provides the <a |
| 73 | href="http://arduino.cc/en/Main/ArduinoBoardADK">Arduino Mega ADK</a> (for EU nations or non- |
| 74 | EU nations) that is based on the ATmega2560 and supports the ADK firmware.</li> |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 75 | |
| 76 | <li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">DIY |
| 77 | Drones</a> provides an Arduino-compatible board geared towards RC (radio controlled) and UAV |
| 78 | (unmanned aerial vehicle) enthusiasts.</li> |
| 79 | |
| 80 | <li><a href="http://mbed.org/order/">mbed</a> provides a microcontroller and a library |
| 81 | to develop accessories that support the Android accessory protocol. For more information, see |
| 82 | <a href="http://mbed.org/cookbook/mbed-with-Android-ADK">mbed with the Android ADK</a>. |
| 83 | </li> |
| 84 | |
| 85 | <li><a href="http://www.microchip.com/android">Microchip</a> provides a PIC based USB |
| 86 | microcontroller board.</li> |
| 87 | |
| 88 | <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">Modern |
| 89 | Device</a> provides an Arduino-compatible board that supports the ADK firmware.</li> |
| 90 | |
| 91 | <li><a href="http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1"> |
| 92 | RT Corp</a> provides an Arduino-compatible board based on the Android ADK board design.</li> |
| 93 | |
| 94 | <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html"> |
| 95 | Seeed Studio</a> provides an Arduino-compatible board that supports the ADK firmware.</li> |
| 96 | |
| 97 | <li><a href="http://www.sparkfun.com/products/10748"> |
| 98 | SparkFun</a>'s IOIO board now has beta support for the ADK firmware.</li> |
| 99 | |
Joe Fernandez | 3a77ccc | 2012-06-24 23:58:25 -0700 | [diff] [blame] | 100 | <li><a href="http://troido.de/de/shoplsmallgbuy-android-stufflsmallg">Troido</a> has produced an |
| 101 | Arduino-compatible version of the ADK hardware.</li> |
| 102 | |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 103 | </ul> |
| 104 | |
| 105 | <p>We expect more hardware distributers to create a variety of kits, so please stay tuned for |
| 106 | further developments.</p> |
| 107 | |
| 108 | <h2 id="components">ADK Components</h2> |
Joe Fernandez | 3a77ccc | 2012-06-24 23:58:25 -0700 | [diff] [blame] | 109 | |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 110 | <p>The main hardware and software components of the ADK include:</p> |
| 111 | |
| 112 | <ul> |
| 113 | <li>A USB micro-controller board that is based on the Arduino Mega2560 and Circuits@Home USB |
| 114 | Host Shield designs (now referred to as the ADK board), which you will later implement as an |
| 115 | Android USB accessory. The ADK board provides input and output pins that you can implement |
| 116 | through the use of attachments called "shields." Custom firmware, written in C++, is installed |
| 117 | on the board to define the board's functionality and interaction with the attached shield and |
| 118 | Android-powered device. The hardware design files for the board are located in |
| 119 | <code>hardware/</code> directory.</li> |
| 120 | |
| 121 | <li>An Android Demo Shield (ADK shield) that affixes atop the ADK board implements the input |
| 122 | and output points on the board. These implementations include a joystick, LED outputs, and |
| 123 | temperature and light sensors. You can create or buy your own shields or wire your own features |
| 124 | to the ADK board to implement custom functionality. The hardware design files for the shield |
| 125 | are located in <code>hardware/</code>.</li> |
| 126 | |
| 127 | <li>A library based on the <a href= |
| 128 | "http://www.circuitsathome.com/arduino_usb_host_shield_projects">Arduino USB Host Shield</a> |
| 129 | library provides the logic for the USB micro-controller board to act as a USB Host. This allows |
| 130 | the board to initiate transactions with USB devices. Describing how to use this entire library |
| 131 | is beyond the scope of this document. Where needed, this document points out important |
| 132 | interactions with the library. For more information, see the source code for the Arduino USB |
| 133 | Host Shield library in the <code>arduino_libs/USB_Host_Shield</code> directory.</li> |
| 134 | |
| 135 | <li>An Arduino sketch, <code>arduino_libs/AndroidAccessory/examples/demokit/demokit.pde</code>, |
| 136 | defines the firmware that |
| 137 | runs on the ADK board and is written in C++. The sketch calls the Android accessory protocol |
| 138 | library to interact with the Android-powered device. It also sends data from the ADK board and |
| 139 | shield to the Android application and receives data from the Android application and outputs it |
| 140 | to the ADK board and shield.</li> |
| 141 | |
| 142 | <li>The Android accessory protocol library, which is located in the |
| 143 | <code>arduino_libs/AndroidAccessory</code> directory. This library defines how to |
| 144 | enumerate the bus, find a connected Android-powered device that supports accessory mode, and |
| 145 | how to setup communication with the device.</li> |
| 146 | |
| 147 | <li>Other third party libraries to support the ADK board's functionality: |
| 148 | <ul> |
| 149 | <li><a href="http://www.arduino.cc/playground/Main/CapSense">CapSense library</a></li> |
| 150 | |
| 151 | <li><a href="http://www.arduino.cc/playground/Learning/I2C">I2C / TWI (Two-Wire Interface) |
| 152 | library</a></li> |
| 153 | |
| 154 | <li><a href="http://www.arduino.cc/playground/ComponentLib/Servo">Servo library</a></li> |
| 155 | |
| 156 | <li><a href="http://www.arduino.cc/playground/Code/Spi">Spi library</a></li> |
| 157 | |
| 158 | <li><a href="http://www.arduino.cc/en/Reference/Wire">Wire library</a></li> |
| 159 | |
| 160 | <li>An Android application, DemoKit, that communicates with the ADK board and shield. The |
| 161 | source for this project is in the <code>app/</code> directory.</li> |
| 162 | </ul> |
| 163 | </li> |
| 164 | |
| 165 | </ul> |
| 166 | |
| 167 | <h2 id="getting-started">Getting Started with the ADK</h2> |
| 168 | |
| 169 | <p>The following sections describe how to install the Arduino software on your computer, use the |
| 170 | Arduino IDE to install the ADK board's firmware, and install and run the accompanying |
| 171 | Android application for the ADK board. Before you begin, download the following items to set up |
| 172 | your development environment:</p> |
| 173 | |
| 174 | <ul> |
| 175 | <li><a href="http://arduino.cc/en/Main/Software">Arduino 1.0 or higher</a>: contains |
| 176 | libraries and an IDE for coding and installing firmware to the ADK board.</li> |
| 177 | |
| 178 | <li><a href="http://www.arduino.cc/playground/Main/CapSense">CapSense library v.04</a>: |
| 179 | contains the libraries to sense human capacitance. This library is needed for the capacitive |
| 180 | button that is located on the ADK shield.</li> |
| 181 | |
| 182 | <li><a href="https://dl-ssl.google.com/android/adk/adk_release_20120606.zip">ADK software |
| 183 | package</a>: contains the firmware for the ADK board and hardware design files for the ADK |
| 184 | board and shield.</li> |
| 185 | </ul> |
| 186 | |
| 187 | <h3 id="installing">Installing the Arduino software and necessary libraries</h3> |
| 188 | |
| 189 | <p>To install the Arduino software:</p> |
| 190 | |
| 191 | <ol> |
| 192 | <li> |
| 193 | <a href="http://arduino.cc/en/Main/Software">Download and install</a> the Arduino 1.0 or |
| 194 | higher as described on the Arduino website. |
| 195 | |
| 196 | <p class="note"><strong>Note:</strong> If you are on a Mac, install the FTDI USB Serial |
| 197 | Driver that is included in the Arduino package, even though the installation instructions say |
| 198 | otherwise.</p> |
| 199 | </li> |
| 200 | |
| 201 | <li><a href="https://dl-ssl.google.com/android/adk/adk_release_20120606.zip">Download</a> and |
| 202 | extract the ADK package to a directory of your choice. You should have an <code>app</code>, |
| 203 | <code>arduino_libs</code>, and <code>hardware</code> directories.</li> |
| 204 | |
| 205 | <li><a href="http://www.arduino.cc/playground/Main/CapSense">Download</a> and extract |
| 206 | the CapSense package to a directory of your choice.</li> |
| 207 | |
| 208 | <li>Install the necessary libraries: |
| 209 | |
| 210 | <p>On Windows:</p> |
| 211 | |
| 212 | <ol type="a"> |
| 213 | <li>Copy the <code>arduino_libs/AndroidAccessory</code> and |
| 214 | <code>arduino_libs/USB_Host_Shield</code> directories (the complete directories, |
| 215 | not just the files within) to the <code><arduino_installation_root>/libraries/</code> |
| 216 | directory.</li> |
| 217 | |
| 218 | <li>Copy the extracted <code>CapSense/</code> library directory and its contents to the |
| 219 | <code><arduino_installation_root>/libraries/</code> directory.</li> |
| 220 | </ol> |
| 221 | |
| 222 | <p>On Mac:</p> |
| 223 | |
| 224 | <ol type="a"> |
| 225 | <li>Create, if it does not already exist, an <code>Arduino</code> |
| 226 | directory inside your user account's <code>Documents</code> directory, and within |
| 227 | that, a <code>libraries</code> directory.</li> |
| 228 | |
| 229 | <li>Copy the <code>arduino_libs/AndroidAccessory</code> and |
| 230 | <code>arduino_libs/USB_Host_Shield</code> directories (the |
| 231 | complete directories, not just the files within) to your |
| 232 | <code>Documents/Arduino/libraries/</code> directory.</li> |
| 233 | |
| 234 | <li>Copy the extracted <code>CapSense/</code> library directory and its contents to the |
| 235 | <code>Documents/Arduino/libraries/</code> directory. |
| 236 | </ol> |
| 237 | |
| 238 | <p>On Linux (Ubuntu):</p> |
| 239 | |
| 240 | <ol type="a"> |
| 241 | <li>Copy the <code>firmware/arduino_libs/AndroidAccessory</code> and |
| 242 | <code>firmware/arduino_libs/USB_Host_Shield</code> directories (the complete directories, |
| 243 | not just the files within) to the <code><arduino_installation_root>/libraries/</code> |
| 244 | directory.</li> |
| 245 | |
| 246 | <li>Copy the extracted <code>CapSense/</code> library directory and its contents to the |
| 247 | <code><arduino_installation_root>/libraries/</code> directory.</li> |
| 248 | |
| 249 | <li>Install the avr-libc library by entering <code>sudo apt-get install avr-libc</code> |
| 250 | from a shell prompt.</li> |
| 251 | </ol> |
| 252 | </li> |
| 253 | </ol> |
| 254 | |
| 255 | <p>You should now have three new directories in the Arduino <code>libraries/</code> directory: |
| 256 | <code>AndroidAccessory</code>, <code>USB_Host_Shield</code>, and <code>CapSense</code>.</p> |
| 257 | |
| 258 | <h3 id="installing-firmware">Installing the firmware to the ADK board</h3> |
| 259 | |
| 260 | <p>To install the firmware to the ADK board:</p> |
| 261 | |
| 262 | <ol> |
| 263 | <li>Connect the ADK board to your computer using the micro-USB port, which allows two-way |
| 264 | communication and provides power to the ADK board.</li> |
| 265 | |
| 266 | <li>Launch the Arduino IDE.</li> |
| 267 | |
| 268 | <li>Click <strong>Tools > Board > Arduino Mega 2560</strong> to specify the ADK board's |
| 269 | type.</li> |
| 270 | |
| 271 | <li>Select the appropriate USB port: |
| 272 | |
| 273 | <ul> |
| 274 | <li>On Windows: click <strong>Tools > Serial Port > COM#</strong> to specify the port |
| 275 | of communication. The COM port number varies depending on your computer. COM1 is usually |
| 276 | reserved for serial port connections. You most likely want COM2 or COM3.</li> |
| 277 | |
| 278 | <li>On Mac: Click <strong>Tools > Serial Port > dev/tty.usbserial-###</strong> to |
| 279 | specify the port of communication.</li> |
| 280 | |
| 281 | <li>On Linux (Ubuntu): Click <strong>Tools > Serial Port > dev/ttyUSB#</strong> to |
| 282 | specify the port of communication.</li> |
| 283 | </ul> |
| 284 | </li> |
| 285 | |
| 286 | <li>To open the Demokit sketch (firmware code), click <strong>File > Examples > |
| 287 | AndroidAccessory > demokit</strong>.</li> |
| 288 | |
| 289 | <li>Click <strong>Sketch > Verify/Compile</strong> to ensure that the sketch has no |
| 290 | errors.</li> |
| 291 | |
| 292 | <li>Select <strong>File > Upload</strong>. When Arduino outputs <strong>Done |
| 293 | uploading.</strong>, the board is ready to communicate with your Android-powered device.</li> |
| 294 | </ol> |
| 295 | |
| 296 | <h3 id="running-demokit">Running the DemoKit Android application</h3> |
| 297 | |
| 298 | <p>The DemoKit Android application runs on your Android-powered device and communicates with the |
| 299 | ADK board. The ADK board receives commands such as lighting up the board's LEDs or sends data |
| 300 | from the board such as joystick movement and temperature readings.</p> |
| 301 | |
| 302 | <p>To install and run the application in Eclipse:</p> |
| 303 | |
| 304 | <ol> |
| 305 | <li><a href="http://code.google.com/android/add-ons/google-apis/installing.html">Install the |
| 306 | Google APIs API Level 10 add-on library</a>, which includes the Open Accessory library for |
| 307 | 2.3.4 devices that support accessory mode. This library is also forward compatible with Android |
| 308 | 3.1 or newer devices that support accessory mode. If you only care about Android 3.1 or newer |
| 309 | devices, all you need is API Level 12. For more information on deciding which API level to use, |
| 310 | see the <a href="{@docRoot}guide/topics/connectivity/usb/accessory.html#choosing">USB Accessory</a> |
| 311 | documentation.</li> |
| 312 | |
| 313 | <li>Click <strong>File > New > Project...</strong>, then select <strong>Android > |
| 314 | Android Project</strong></li> |
| 315 | |
| 316 | <li>In the <strong>Project name:</strong> field, type DemoKit.</li> |
| 317 | |
| 318 | <li>Choose <strong>Create project from existing source</strong>, click <strong>Browse</strong>, |
| 319 | select the <code>app</code> directory, click <strong>Open</strong> to close that dialog and then |
| 320 | click <strong>Finish</strong>.</li> |
| 321 | |
| 322 | <li>For Build Target, select <strong>Google APIs</strong> (Platform 2.3.3, API Level 10). |
| 323 | |
| 324 | <p class="note"><strong>Note:</strong> Even though the add-on is labeled as |
| 325 | <strong>2.3.3</strong>, the newest Google API add-on library for API level 10 adds USB Open |
| 326 | Accessory API support for 2.3.4 devices.</p> |
| 327 | </li> |
| 328 | |
| 329 | <li>Click <strong>Finish</strong>.</li> |
| 330 | |
| 331 | <li>Install the application to your device.</li> |
| 332 | |
| 333 | <li>Connect the ADK board (USB-A) to your Android-powered device (micro-USB). Ensure that the |
| 334 | power cable to the accessory is plugged in or that the micro-USB port on the accesory is |
| 335 | connected to your computer for power (this also allows you to <a href="#monitoring">monitor the |
| 336 | ADK board</a>). When connected, accept the prompt that asks for whether or not to open the |
| 337 | DemoKit application to connect to the accessory. If the prompt does not show up, connect and |
| 338 | reconnect the accessory.</li> |
| 339 | </ol> |
| 340 | |
| 341 | <p>You can now interact with the ADK board by moving the color LED or servo sliders (make sure |
| 342 | the servos are connected) or by pressing the relay buttons in the application. On the ADK shield, |
| 343 | you can press the buttons and move the joystick to see their outputs displayed in the |
| 344 | application.</p> |
| 345 | |
| 346 | <h3 id="monitoring">Monitoring the ADK Board</h3> |
| 347 | |
| 348 | <p>The ADK firmware consists of a few files that you should be looking at if you want to build |
| 349 | your own accessory. The files in the <code>arduino_libs/AndroidAccessory</code> |
| 350 | directory are the most important files and have the logic to detect and connect to |
| 351 | Android-powered devices that support accessory mode. Feel free to add debug statements (Arduino |
| 352 | <code>Serial.println()</code> statements) to the code located in the |
| 353 | <code><arduino_installation_root>/libraries/AndroidAccessory</code> directory and |
| 354 | <code>demokit.pde</code> sketch and re-upload the sketch to the ADK board to |
| 355 | discover more about how the firmware works.</p> |
| 356 | |
| 357 | <p>You can view the debug statements in the Arduino Serial Monitor by clicking <strong>Tools > |
| 358 | Serial Monitor</strong> and setting the baud to 115200. The following sections about how |
| 359 | accessories communicate with Android-powered devices describe much of what you should be doing in |
| 360 | your own accessory.</p> |
| 361 | |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 362 | <h2 id="firmware">How the ADK board implements the Android Accessory protocol</h2> |
| 363 | |
| 364 | <p>If you have access to the ADK board and shield, the following sections describe the firmware |
| 365 | code that you installed onto the ADK board. The firmware demonstrates a practical example of how |
| 366 | to implement the Android Accessory protocol. Even if you do not have the ADK board and shield, |
| 367 | reading through how the hardware detects and interacts with devices in accessory mode is still |
| 368 | useful if you want to port the code over for your own accessories.</p> |
| 369 | |
| 370 | <p>The important pieces of the firmware are the |
| 371 | <code>arduino_libs/AndroidAccessory/examples/demokit/demokit/demokit.pde</code> sketch, which is |
| 372 | the code that receives and sends data to the DemoKit application running on the Android-powered |
| 373 | device. The code to detect and set up communication with the Android-powered device is contained |
| 374 | in the <code>arduino_libs/AndroidAccessory/AndroidAccessory.h</code> and |
| 375 | <code>arduino_libs/AndroidAccessory/AndroidAccessory.cpp</code> files. This code |
| 376 | includes most of the logic that will help you implement your own accessory's firmware. It might |
| 377 | be useful to have all three of these files open in a text editor as you read through these next |
| 378 | sections.</p> |
| 379 | |
| 380 | <p>The following sections describe the firmware code in the context of the algorithm described in |
| 381 | <a href="#accessory-protocol">Implementing the Android Accessory Protocol</a>.</p> |
| 382 | |
| 383 | <h3 id="wait-adk">Wait for and detect connected devices</h3> |
| 384 | |
| 385 | <p>In the firmware code (<code>demokit.pde</code>), the <code>loop()</code> function runs |
| 386 | repeatedly and calls <code>AndroidAccessory::isConnected()</code> to check for any connected |
| 387 | devices. If there is a connected device, it continuously updates the input and output streams |
| 388 | going to and from the board and application. If nothing is connected, it continuously checks for |
| 389 | a device to be connected:</p> |
| 390 | <pre> |
| 391 | ... |
| 392 | |
| 393 | AndroidAccessory acc("Google, Inc.", |
| 394 | "DemoKit", |
| 395 | "DemoKit Arduino Board", |
| 396 | "1.0", |
| 397 | "http://www.android.com", |
| 398 | "0000000012345678"); |
| 399 | |
| 400 | ... |
| 401 | void loop() |
| 402 | { |
| 403 | ... |
| 404 | if (acc.isConnected()) { |
| 405 | //communicate with Android application |
| 406 | } |
| 407 | else{ |
| 408 | //set the accessory to its default state |
| 409 | } |
| 410 | ... |
| 411 | } |
| 412 | </pre> |
| 413 | |
| 414 | <h3 id="determine-adk">Determine the connected device's accessory mode support</h3> |
| 415 | |
| 416 | <p>When a device is connected to the ADK board, it can already be in accessory mode, support |
| 417 | accessory mode and is not in that mode, or does not support accessory mode. The |
| 418 | <code>AndroidAccessory::isConnected()</code> method checks for these cases and responds |
| 419 | accordingly when the <code>loop()</code> function calls it. This function first checks to see if |
| 420 | the device that is connected hasn't already been handled. If not, it gets the connected device's |
| 421 | device descriptor to figure out if the device is already in accessory mode by calling |
| 422 | <code>AndroidAccessory::isAccessoryDevice()</code>. This method checks the vendor and product ID |
| 423 | of the device descriptor. A device in accessory mode has a vendor ID of 0x18D1 and a product ID |
| 424 | of 0x2D00 or 0x2D01. If the device is in accessory mode, then the ADK board can <a href= |
| 425 | "#establish">establish communication with the device</a>. If not, the board <a href= |
| 426 | "#start">attempts to start the device in accessory mode</a>.</p> |
| 427 | <pre> |
| 428 | bool AndroidAccessory::isConnected(void) |
| 429 | { |
| 430 | USB_DEVICE_DESCRIPTOR *devDesc = (USB_DEVICE_DESCRIPTOR *) descBuff; |
| 431 | byte err; |
| 432 | |
| 433 | max.Task(); |
| 434 | usb.Task(); |
| 435 | |
| 436 | if (!connected && |
| 437 | usb.getUsbTaskState() >= USB_STATE_CONFIGURING && |
| 438 | usb.getUsbTaskState() != USB_STATE_RUNNING) { |
| 439 | Serial.print("\nDevice addressed... "); |
| 440 | Serial.print("Requesting device descriptor."); |
| 441 | |
| 442 | err = usb.getDevDescr(1, 0, 0x12, (char *) devDesc); |
| 443 | if (err) { |
| 444 | Serial.print("\nDevice descriptor cannot be retrieved. Program Halted\n"); |
| 445 | while(1); |
| 446 | } |
| 447 | |
| 448 | if (isAccessoryDevice(devDesc)) { |
| 449 | Serial.print("found android accessory device\n"); |
| 450 | |
| 451 | connected = configureAndroid(); |
| 452 | } else { |
| 453 | Serial.print("found possible device. switching to serial mode\n"); |
| 454 | switchDevice(1); |
| 455 | } |
| 456 | } else if (usb.getUsbTaskState() == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) { |
| 457 | connected = false; |
| 458 | } |
| 459 | |
| 460 | return connected; |
| 461 | } |
| 462 | </pre> |
| 463 | |
| 464 | <h3 id="start-adk">Attempt to start the device in accessory mode</h3> |
| 465 | |
| 466 | <p>If the device is not already in accessory mode, then the ADK board must determine whether or |
| 467 | not it supports it by sending control request 51 to check the version of the USB accessory |
| 468 | protocol that the device supports (see <code>AndroidAccessory::getProtocol()</code>). Protocol |
Joe Fernandez | 3a77ccc | 2012-06-24 23:58:25 -0700 | [diff] [blame] | 469 | version 1 is supported by Android 2.3.4 (API Level 10) and higher. Protocol version 2 is |
| 470 | supported by Android 4.1 (API Level 16) and higher. Versions greater than 2 may supported in |
| 471 | the future. |
| 472 | If the appropriate protocol version is returned, the board sends control request 52 (one |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 473 | for each string with <code>AndroidAcessory:sendString()</code>) to send it's identifying |
| 474 | information, and tries to start the device in accessory mode with control request 53. The |
| 475 | <code>AndroidAccessory::switchDevice()</code> method takes care of this:</p> |
| 476 | <pre> |
| 477 | bool AndroidAccessory::switchDevice(byte addr) |
| 478 | { |
| 479 | int protocol = getProtocol(addr); |
Joe Fernandez | 3a77ccc | 2012-06-24 23:58:25 -0700 | [diff] [blame] | 480 | if (protocol >= 1) { |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 481 | Serial.print("device supports protocol 1\n"); |
| 482 | } else { |
| 483 | Serial.print("could not read device protocol version\n"); |
| 484 | return false; |
| 485 | } |
| 486 | |
| 487 | sendString(addr, ACCESSORY_STRING_MANUFACTURER, manufacturer); |
| 488 | sendString(addr, ACCESSORY_STRING_MODEL, model); |
| 489 | sendString(addr, ACCESSORY_STRING_DESCRIPTION, description); |
| 490 | sendString(addr, ACCESSORY_STRING_VERSION, version); |
| 491 | sendString(addr, ACCESSORY_STRING_URI, uri); |
| 492 | sendString(addr, ACCESSORY_STRING_SERIAL, serial); |
| 493 | |
| 494 | usb.ctrlReq(addr, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE, |
| 495 | ACCESSORY_START, 0, 0, 0, 0, NULL); |
| 496 | return true; |
| 497 | } |
| 498 | </pre>If this method returns false, the board waits until a new device is connected. If it is |
| 499 | successful, the device displays itself on the USB bus as being in accessory mode when the ADK board |
| 500 | re-enumerates the bus. When the device is in accessory mode, the accessory then <a href= |
| 501 | "#establish-adk">establishes communication with the device</a>. |
| 502 | |
| 503 | <h3 id="establish-adk">Establish communication with the device</h3> |
| 504 | |
| 505 | <p>If a device is detected as being in accessory mode, the accessory must find the proper bulk |
| 506 | endpoints and set up communication with the device. When the ADK board detects an Android-powered |
| 507 | device in accessory mode, it calls the <code>AndroidAccessory::configureAndroid()</code> |
| 508 | function:</p> |
| 509 | <pre> |
| 510 | ... |
| 511 | if (isAccessoryDevice(devDesc)) { |
| 512 | Serial.print("found android acessory device\n"); |
| 513 | |
| 514 | connected = configureAndroid(); |
| 515 | } |
| 516 | ... |
| 517 | </pre> |
| 518 | |
| 519 | <p>which in turn calls the <code>findEndpoints()</code> function:</p> |
| 520 | <pre> |
| 521 | ... |
| 522 | bool AndroidAccessory::configureAndroid(void) |
| 523 | { |
| 524 | byte err; |
| 525 | EP_RECORD inEp, outEp; |
| 526 | |
| 527 | if (!findEndpoints(1, &inEp, &outEp)) |
| 528 | return false; |
| 529 | ... |
| 530 | </pre> |
| 531 | |
| 532 | <p>The <code>AndroidAccessory::findEndpoints()</code> function queries the Android-powered |
| 533 | device's configuration descriptor and finds the bulk data endpoints in which to communicate with |
| 534 | the USB device. To do this, it first gets the device's first four bytes of the configuration |
| 535 | descriptor (only need descBuff[2] and descBuff[3]), which contains the information about the |
| 536 | total length of data returned by getting the descriptor. This data is used to determine whether |
| 537 | or not the descriptor can fit in the descriptor buffer. This descriptor also contains information |
| 538 | about all the interfaces and endpoint descriptors. If the descriptor is of appropriate size, the |
| 539 | method reads the entire configuration descriptor and fills the entire descriptor buffer with this |
| 540 | device's configuration descriptor. If for some reason the descriptor is no longer attainable, an |
| 541 | error is returned.</p> |
| 542 | <pre> |
| 543 | ... |
| 544 | |
| 545 | bool AndroidAccessory::findEndpoints(byte addr, EP_RECORD *inEp, EP_RECORD *outEp) |
| 546 | { |
| 547 | int len; |
| 548 | byte err; |
| 549 | uint8_t *p; |
| 550 | |
| 551 | err = usb.getConfDescr(addr, 0, 4, 0, (char *)descBuff); |
| 552 | if (err) { |
| 553 | Serial.print("Can't get config descriptor length\n"); |
| 554 | return false; |
| 555 | } |
| 556 | |
| 557 | |
| 558 | len = descBuff[2] | ((int)descBuff[3] << 8); |
| 559 | if (len > sizeof(descBuff)) { |
| 560 | Serial.print("config descriptor too large\n"); |
| 561 | /* might want to truncate here */ |
| 562 | return false; |
| 563 | } |
| 564 | |
| 565 | err = usb.getConfDescr(addr, 0, len, 0, (char *)descBuff); |
| 566 | if (err) { |
| 567 | Serial.print("Can't get config descriptor\n"); |
| 568 | return false; |
| 569 | } |
| 570 | |
| 571 | ... |
| 572 | </pre> |
| 573 | |
| 574 | <p>Once the descriptor is in memory, a pointer is assigned to the first position of the buffer |
| 575 | and is used to index the buffer for reading. There are two endpoint pointers (input and output) |
| 576 | that are passed into <code>AndroidAccessory::findEndpoints()</code> and their addresses are set |
| 577 | to 0, because the code hasn't found any suitable bulk endpoints yet. A loop reads the buffer, |
| 578 | parsing each configuration, interface, or endpoint descriptor. For each descriptor, Position 0 |
| 579 | always contains the size of the descriptor in bytes and position 1 always contains the descriptor |
| 580 | type. Using these two values, the loop skips any configuration and interface descriptors and |
| 581 | increments the buffer with the <code>descLen</code> variable to get to the next descriptor.</p> |
| 582 | |
| 583 | <p class="note"><strong>Note:</strong> An Android-powered device in accessory mode can |
| 584 | potentially have two interfaces, one for the default communication to the device and the other |
| 585 | for ADB communication. The default communication interface is always indexed first, so finding |
| 586 | the first input and output bulk endpoints will return the default communication endpoints, which |
| 587 | is what the <code>demokit.pde</code> sketch does. If you are writing your own firmware, the logic |
| 588 | to find the appropriate endpoints for your accessory might be different.</p> |
| 589 | |
| 590 | <p>When it finds the first input and output endpoint descriptors, it sets the endpoint pointers |
| 591 | to those addresses. If the findEndpoints() function finds both an input and output endpoint, it |
| 592 | returns true. It ignores any other endpoints that it finds (the endpoints for the ADB interface, |
| 593 | if present).</p> |
| 594 | <pre> |
| 595 | ... |
| 596 | p = descBuff; |
| 597 | inEp->epAddr = 0; |
| 598 | outEp->epAddr = 0; |
| 599 | while (p < (descBuff + len)){ |
| 600 | uint8_t descLen = p[0]; |
| 601 | uint8_t descType = p[1]; |
| 602 | USB_ENDPOINT_DESCRIPTOR *epDesc; |
| 603 | EP_RECORD *ep; |
| 604 | |
| 605 | switch (descType) { |
| 606 | case USB_DESCRIPTOR_CONFIGURATION: |
| 607 | Serial.print("config desc\n"); |
| 608 | break; |
| 609 | |
| 610 | case USB_DESCRIPTOR_INTERFACE: |
| 611 | Serial.print("interface desc\n"); |
| 612 | break; |
| 613 | |
| 614 | case USB_DESCRIPTOR_ENDPOINT: |
| 615 | epDesc = (USB_ENDPOINT_DESCRIPTOR *)p; |
| 616 | if (!inEp->epAddr && (epDesc->bEndpointAddress & 0x80)) |
| 617 | ep = inEp; |
| 618 | else if (!outEp->epAddr) |
| 619 | ep = outEp; |
| 620 | else |
| 621 | ep = NULL; |
| 622 | |
| 623 | if (ep) { |
| 624 | ep->epAddr = epDesc->bEndpointAddress & 0x7f; |
| 625 | ep->Attr = epDesc->bmAttributes; |
| 626 | ep->MaxPktSize = epDesc->wMaxPacketSize; |
| 627 | ep->sndToggle = bmSNDTOG0; |
| 628 | ep->rcvToggle = bmRCVTOG0; |
| 629 | } |
| 630 | break; |
| 631 | |
| 632 | default: |
| 633 | Serial.print("unkown desc type "); |
| 634 | Serial.println( descType, HEX); |
| 635 | break; |
| 636 | } |
| 637 | |
| 638 | p += descLen; |
| 639 | } |
| 640 | |
| 641 | if (!(inEp->epAddr && outEp->epAddr)) |
| 642 | Serial.println("can't find accessory endpoints"); |
| 643 | |
| 644 | return inEp->epAddr && outEp->epAddr; |
| 645 | } |
| 646 | |
| 647 | ... |
| 648 | </pre> |
| 649 | |
| 650 | <p>Back in the <code>configureAndroid()</code> function, if there were endpoints found, they are |
| 651 | appropriately set up for communication. The device's configuration is set to 1 and the state of |
| 652 | the device is set to "running", which signifies that the device is properly set up to communicate |
| 653 | with your USB accessory. Setting this status prevents the device from being re-detected and |
| 654 | re-configured in the <code>AndroidAccessory::isConnected()</code> function.</p> |
| 655 | <pre> |
| 656 | bool AndroidAccessory::configureAndroid(void) |
| 657 | { |
| 658 | byte err; |
| 659 | EP_RECORD inEp, outEp; |
| 660 | |
| 661 | if (!findEndpoints(1, &inEp, &outEp)) |
| 662 | return false; |
| 663 | |
| 664 | memset(&epRecord, 0x0, sizeof(epRecord)); |
| 665 | |
| 666 | epRecord[inEp.epAddr] = inEp; |
| 667 | if (outEp.epAddr != inEp.epAddr) |
| 668 | epRecord[outEp.epAddr] = outEp; |
| 669 | |
| 670 | in = inEp.epAddr; |
| 671 | out = outEp.epAddr; |
| 672 | |
| 673 | Serial.print("inEp: "); |
| 674 | Serial.println(inEp.epAddr, HEX); |
| 675 | Serial.print("outEp: "); |
| 676 | Serial.println(outEp.epAddr, HEX); |
| 677 | |
| 678 | epRecord[0] = *(usb.getDevTableEntry(0,0)); |
| 679 | usb.setDevTableEntry(1, epRecord); |
| 680 | |
| 681 | err = usb.setConf( 1, 0, 1 ); |
| 682 | if (err) { |
| 683 | Serial.print("Can't set config to 1\n"); |
| 684 | return false; |
| 685 | } |
| 686 | |
| 687 | usb.setUsbTaskState( USB_STATE_RUNNING ); |
| 688 | |
| 689 | return true; |
| 690 | } |
| 691 | </pre> |
| 692 | |
| 693 | <p>Lastly, methods to read and write to the appropriate endpoints are needed. The |
| 694 | <code>demokit.pde</code> sketch calls these methods depending on the data that is read from the |
| 695 | Android-powered device or sent by the ADK board. For instance, moving the joystick on the ADK |
| 696 | shield writes data that is read by the DemoKit application running on the Android-powered device. |
| 697 | Moving sliders on the DemoKit application is read by the <code>demokit.pde</code> sketch and |
| 698 | changes the state of the accessory, such as lighting up or changing the color of the LED |
| 699 | lights.</p> |
| 700 | <pre> |
| 701 | int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit) { |
| 702 | return usb.newInTransfer(1, in, len, (char *)buff, nakLimit); } |
| 703 | |
| 704 | int AndroidAccessory::write(void *buff, int len) { |
| 705 | usb.outTransfer(1, out, len, (char *)buff); |
| 706 | return len; } |
| 707 | </pre> |
| 708 | |
| 709 | <p>See the <code>demokit.pde</code> sketch for information about how the ADK board |
| 710 | reads and writes data.</p> |