diff options
author | Joe Fernandez <joefernandez@google.com> | 2012-06-24 23:58:25 -0700 |
---|---|---|
committer | Joe Fernandez <joefernandez@google.com> | 2012-06-26 02:24:32 -0700 |
commit | 3a77ccc63f11b26067f03ef61a713ff2599fbb5f (patch) | |
tree | 43ad90f9f03bea680d81045e6d07fd6b3f3bf290 /docs/html/guide/topics/connectivity | |
parent | dbbfa702a09f6d2d36dee1b552442d04a4673f89 (diff) | |
download | frameworks_base-3a77ccc63f11b26067f03ef61a713ff2599fbb5f.zip frameworks_base-3a77ccc63f11b26067f03ef61a713ff2599fbb5f.tar.gz frameworks_base-3a77ccc63f11b26067f03ef61a713ff2599fbb5f.tar.bz2 |
docs: ADK 2012 documentation with AOA protocol docs
Change-Id: Ife96b3ffa890d42fc97125b30bdd389448645562
Diffstat (limited to 'docs/html/guide/topics/connectivity')
-rw-r--r-- | docs/html/guide/topics/connectivity/usb/adk.jd | 909 |
1 files changed, 0 insertions, 909 deletions
diff --git a/docs/html/guide/topics/connectivity/usb/adk.jd b/docs/html/guide/topics/connectivity/usb/adk.jd deleted file mode 100644 index 034728c..0000000 --- a/docs/html/guide/topics/connectivity/usb/adk.jd +++ /dev/null @@ -1,909 +0,0 @@ -page.title=Android Open Accessory Development Kit -@jd:body - - <div id="qv-wrapper"> - <div id="qv"> - <h2>In this document</h2> - - <ol> - <li><a href="#components">ADK Components</a></li> - <li> - - <a href="#getting-started">Getting Started with the ADK</a> - - <ol> - <li><a href="#installing">Installing the Arduino software and necessary - libraries</a></li> - - <li><a href="#installing-firmware">Installing the firmware to the ADK board</a></li> - - <li><a href="#running-demokit">Running the DemoKit Android application</a></li> - - <li><a href="#monitoring">Monitoring the ADK board</a></li> - </ol> - </li> - - <li> - <a href="#accessory-protocol">Implementing the Android Accessory Protocol</a> - - <ol> - <li><a href="#wait">Wait for and detect connected devices</a></li> - - <li><a href="#determine">Determine the connected device's accessory mode - support</a></li> - - <li><a href="#start">Attempt to start the device in accessory mode</a></li> - - <li><a href="#establish">Establish communication with the device</a></li> - </ol> - </li> - - <li> - <a href="#firmware">How the ADK board implements the Android Accessory Protocol</a> - - <ol> - <li><a href="#wait-adk">Wait for and detect connected devices</a></li> - - <li><a href="#determine-adk">Determine the connected device's accessory mode - support</a></li> - - <li><a href="#start-adk">Attempt to start the device in accessory mode</a></li> - - <li><a href="#establish-adk">Establish communication with the device</a></li> - </ol> - </li> - </ol> - - <h2>Download</h2> - <ol> - <li><a href="https://dl-ssl.google.com/android/adk/adk_release_0512.zip">ADK package</a></li> - </ol> - - <h2>See also</h2> - - <ol> - <li><a href="http://www.youtube.com/watch?v=s7szcpXf2rE">Google I/O Session Video</a></li> - <li><a href="{@docRoot}guide/topics/connectivity/usb/accessory.html">USB Accessory Dev Guide</a></li> - </ol> - - <h2>Where to buy</h2> - - <ol> - - <li><a href="http://store.arduino.cc/"> - Arduino Store</a></li> - - <li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone"> - DIY Drones</a></li> - - <li><a href= - "http://mbed.org/order/"> - mbed</a></li> - - <li><a href= - "http://www.microchip.com/android"> - Microchip</a></li> - - <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board"> - Modern Device</a></li> - - <li><a href= - "http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1"> - RT Corp</a></li> - - <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html"> - Seeed Studio</a></li> - - <li><a href="http://www.sparkfun.com/products/10748"> - SparkFun</a></li> - - <li><a href="http://troido.de/de/shoplsmallgbuy-android-stufflsmallg"> - Troido</a></li> - - </ol> - </div> - </div> - - <p>The Android 3.1 platform (also backported to Android 2.3.4) introduces Android Open Accessory - support, which allows external USB hardware (an Android USB accessory) to interact with an - Android-powered device in a special "accessory" mode. When an Android-powered powered device is - in accessory mode, the connected accessory acts as the USB host (powers the bus and enumerates - devices) and the Android-powered device acts as the USB device. Android USB accessories are - specifically designed to attach to Android-powered devices and adhere to a simple protocol - (Android accessory protocol) that allows them to detect Android-powered devices that support - accessory mode. Accessories must also provide 500mA at 5V for charging power. Many previously - released Android-powered devices are only capable of acting as a USB device and cannot initiate - connections with external USB devices. Android Open Accessory support overcomes this limitation - and allows you to build accessories that can interact with an assortment of Android-powered - devices by allowing the accessory to initiate the connection.</p> - - <p class="note"><strong>Note:</strong> Accessory mode is ultimately dependent on the device's - hardware and not all devices will support accessory mode. Devices that support accessory mode can - be filtered using a <code><uses-feature></code> element in your corresponding application's - Android manifest. For more information, see the <a href= - "{@docRoot}guide/topics/connectivity/usb/accessory.html#manifest">USB Accessory</a> Developer Guide.</p> - - <p>The following list of distributers are currently producing Android Open Accessory compatible - development boards:</p> - - <ul> - - <li>The <a href="http://store.arduino.cc/">Arduino Store</a> provides the Arduino Mega ADK - (in <a href="http://store.arduino.cc/eu/index.php?main_page=product_info&cPath=11_12&products_id=144">EU nations</a> - or <a href="http://store.arduino.cc/ww/index.php?main_page=product_info&cPath=11_12&products_id=144">non-EU nations</a>) - that is based on the ATmega2560 and supports the ADK firmware.</li> - - <li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">DIY - Drones</a> provides an Arduino-compatible board geared towards RC (radio controlled) and UAV - (unmanned aerial vehicle) enthusiasts.</li> - - <li><a href="http://mbed.org/order/">mbed</a> provides a microcontroller and a library - to develop accessories that support the Android accessory protocol. For more information, see - <a href="http://mbed.org/cookbook/mbed-with-Android-ADK">mbed with the Android ADK</a>. - </li> - - <li><a href="http://www.microchip.com/android">Microchip</a> provides a PIC based USB - microcontroller board.</li> - - <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">Modern - Device</a> provides an Arduino-compatible board that supports the ADK firmware.</li> - - <li><a href="http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1"> - RT Corp</a> provides an Arduino-compatible board based on the Android ADK board design.</li> - - <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html"> - Seeed Studio</a> provides an Arduino-compatible board that supports the ADK firmware.</li> - - <li><a href="http://www.sparkfun.com/products/10748"> - SparkFun</a>'s IOIO board now has beta support for the ADK firmware.</li> - - </ul> - - <p>We expect more hardware distributers to create a variety of kits, so please stay tuned for - further developments.</p> - - <h2 id="components">ADK Components</h2> - <p>The Android Open Accessory Development Kit (ADK) provides an implementation of an Android USB - accessory that is based on the <a href="http://www.arduino.cc/">Arduino open source electronics - prototyping platform</a>, the accessory's hardware design files, code that implements the - accessory's firmware, and the Android application that interacts with the accessory. The hardware - design files and firmware code are contained in the <a href= - "https://dl-ssl.google.com/android/adk/adk_release_20120606.zip">ADK package download</a>.</p> - <p>The main hardware and software components of the ADK include:</p> - - <ul> - <li>A USB micro-controller board that is based on the Arduino Mega2560 and Circuits@Home USB - Host Shield designs (now referred to as the ADK board), which you will later implement as an - Android USB accessory. The ADK board provides input and output pins that you can implement - through the use of attachments called "shields." Custom firmware, written in C++, is installed - on the board to define the board's functionality and interaction with the attached shield and - Android-powered device. The hardware design files for the board are located in - <code>hardware/</code> directory.</li> - - <li>An Android Demo Shield (ADK shield) that affixes atop the ADK board implements the input - and output points on the board. These implementations include a joystick, LED outputs, and - temperature and light sensors. You can create or buy your own shields or wire your own features - to the ADK board to implement custom functionality. The hardware design files for the shield - are located in <code>hardware/</code>.</li> - - <li>A library based on the <a href= - "http://www.circuitsathome.com/arduino_usb_host_shield_projects">Arduino USB Host Shield</a> - library provides the logic for the USB micro-controller board to act as a USB Host. This allows - the board to initiate transactions with USB devices. Describing how to use this entire library - is beyond the scope of this document. Where needed, this document points out important - interactions with the library. For more information, see the source code for the Arduino USB - Host Shield library in the <code>arduino_libs/USB_Host_Shield</code> directory.</li> - - <li>An Arduino sketch, <code>arduino_libs/AndroidAccessory/examples/demokit/demokit.pde</code>, - defines the firmware that - runs on the ADK board and is written in C++. The sketch calls the Android accessory protocol - library to interact with the Android-powered device. It also sends data from the ADK board and - shield to the Android application and receives data from the Android application and outputs it - to the ADK board and shield.</li> - - <li>The Android accessory protocol library, which is located in the - <code>arduino_libs/AndroidAccessory</code> directory. This library defines how to - enumerate the bus, find a connected Android-powered device that supports accessory mode, and - how to setup communication with the device.</li> - - <li>Other third party libraries to support the ADK board's functionality: - <ul> - <li><a href="http://www.arduino.cc/playground/Main/CapSense">CapSense library</a></li> - - <li><a href="http://www.arduino.cc/playground/Learning/I2C">I2C / TWI (Two-Wire Interface) - library</a></li> - - <li><a href="http://www.arduino.cc/playground/ComponentLib/Servo">Servo library</a></li> - - <li><a href="http://www.arduino.cc/playground/Code/Spi">Spi library</a></li> - - <li><a href="http://www.arduino.cc/en/Reference/Wire">Wire library</a></li> - - <li>An Android application, DemoKit, that communicates with the ADK board and shield. The - source for this project is in the <code>app/</code> directory.</li> - </ul> - </li> - - </ul> - - <h2 id="getting-started">Getting Started with the ADK</h2> - - <p>The following sections describe how to install the Arduino software on your computer, use the - Arduino IDE to install the ADK board's firmware, and install and run the accompanying - Android application for the ADK board. Before you begin, download the following items to set up - your development environment:</p> - - <ul> - <li><a href="http://arduino.cc/en/Main/Software">Arduino 1.0 or higher</a>: contains - libraries and an IDE for coding and installing firmware to the ADK board.</li> - - <li><a href="http://www.arduino.cc/playground/Main/CapSense">CapSense library v.04</a>: - contains the libraries to sense human capacitance. This library is needed for the capacitive - button that is located on the ADK shield.</li> - - <li><a href="https://dl-ssl.google.com/android/adk/adk_release_20120606.zip">ADK software - package</a>: contains the firmware for the ADK board and hardware design files for the ADK - board and shield.</li> - </ul> - - <h3 id="installing">Installing the Arduino software and necessary libraries</h3> - - <p>To install the Arduino software:</p> - - <ol> - <li> - <a href="http://arduino.cc/en/Main/Software">Download and install</a> the Arduino 1.0 or - higher as described on the Arduino website. - - <p class="note"><strong>Note:</strong> If you are on a Mac, install the FTDI USB Serial - Driver that is included in the Arduino package, even though the installation instructions say - otherwise.</p> - </li> - - <li><a href="https://dl-ssl.google.com/android/adk/adk_release_20120606.zip">Download</a> and - extract the ADK package to a directory of your choice. You should have an <code>app</code>, - <code>arduino_libs</code>, and <code>hardware</code> directories.</li> - - <li><a href="http://www.arduino.cc/playground/Main/CapSense">Download</a> and extract - the CapSense package to a directory of your choice.</li> - - <li>Install the necessary libraries: - - <p>On Windows:</p> - - <ol type="a"> - <li>Copy the <code>arduino_libs/AndroidAccessory</code> and - <code>arduino_libs/USB_Host_Shield</code> directories (the complete directories, - not just the files within) to the <code><arduino_installation_root>/libraries/</code> - directory.</li> - - <li>Copy the extracted <code>CapSense/</code> library directory and its contents to the - <code><arduino_installation_root>/libraries/</code> directory.</li> - </ol> - - <p>On Mac:</p> - - <ol type="a"> - <li>Create, if it does not already exist, an <code>Arduino</code> - directory inside your user account's <code>Documents</code> directory, and within - that, a <code>libraries</code> directory.</li> - - <li>Copy the <code>arduino_libs/AndroidAccessory</code> and - <code>arduino_libs/USB_Host_Shield</code> directories (the - complete directories, not just the files within) to your - <code>Documents/Arduino/libraries/</code> directory.</li> - - <li>Copy the extracted <code>CapSense/</code> library directory and its contents to the - <code>Documents/Arduino/libraries/</code> directory. - </ol> - - <p>On Linux (Ubuntu):</p> - - <ol type="a"> - <li>Copy the <code>firmware/arduino_libs/AndroidAccessory</code> and - <code>firmware/arduino_libs/USB_Host_Shield</code> directories (the complete directories, - not just the files within) to the <code><arduino_installation_root>/libraries/</code> - directory.</li> - - <li>Copy the extracted <code>CapSense/</code> library directory and its contents to the - <code><arduino_installation_root>/libraries/</code> directory.</li> - - <li>Install the avr-libc library by entering <code>sudo apt-get install avr-libc</code> - from a shell prompt.</li> - </ol> - </li> - </ol> - - <p>You should now have three new directories in the Arduino <code>libraries/</code> directory: - <code>AndroidAccessory</code>, <code>USB_Host_Shield</code>, and <code>CapSense</code>.</p> - - <h3 id="installing-firmware">Installing the firmware to the ADK board</h3> - - <p>To install the firmware to the ADK board:</p> - - <ol> - <li>Connect the ADK board to your computer using the micro-USB port, which allows two-way - communication and provides power to the ADK board.</li> - - <li>Launch the Arduino IDE.</li> - - <li>Click <strong>Tools > Board > Arduino Mega 2560</strong> to specify the ADK board's - type.</li> - - <li>Select the appropriate USB port: - - <ul> - <li>On Windows: click <strong>Tools > Serial Port > COM#</strong> to specify the port - of communication. The COM port number varies depending on your computer. COM1 is usually - reserved for serial port connections. You most likely want COM2 or COM3.</li> - - <li>On Mac: Click <strong>Tools > Serial Port > dev/tty.usbserial-###</strong> to - specify the port of communication.</li> - - <li>On Linux (Ubuntu): Click <strong>Tools > Serial Port > dev/ttyUSB#</strong> to - specify the port of communication.</li> - </ul> - </li> - - <li>To open the Demokit sketch (firmware code), click <strong>File > Examples > - AndroidAccessory > demokit</strong>.</li> - - <li>Click <strong>Sketch > Verify/Compile</strong> to ensure that the sketch has no - errors.</li> - - <li>Select <strong>File > Upload</strong>. When Arduino outputs <strong>Done - uploading.</strong>, the board is ready to communicate with your Android-powered device.</li> - </ol> - - <h3 id="running-demokit">Running the DemoKit Android application</h3> - - <p>The DemoKit Android application runs on your Android-powered device and communicates with the - ADK board. The ADK board receives commands such as lighting up the board's LEDs or sends data - from the board such as joystick movement and temperature readings.</p> - - <p>To install and run the application in Eclipse:</p> - - <ol> - <li><a href="http://code.google.com/android/add-ons/google-apis/installing.html">Install the - Google APIs API Level 10 add-on library</a>, which includes the Open Accessory library for - 2.3.4 devices that support accessory mode. This library is also forward compatible with Android - 3.1 or newer devices that support accessory mode. If you only care about Android 3.1 or newer - devices, all you need is API Level 12. For more information on deciding which API level to use, - see the <a href="{@docRoot}guide/topics/connectivity/usb/accessory.html#choosing">USB Accessory</a> - documentation.</li> - - <li>Click <strong>File > New > Project...</strong>, then select <strong>Android > - Android Project</strong></li> - - <li>In the <strong>Project name:</strong> field, type DemoKit.</li> - - <li>Choose <strong>Create project from existing source</strong>, click <strong>Browse</strong>, - select the <code>app</code> directory, click <strong>Open</strong> to close that dialog and then - click <strong>Finish</strong>.</li> - - <li>For Build Target, select <strong>Google APIs</strong> (Platform 2.3.3, API Level 10). - - <p class="note"><strong>Note:</strong> Even though the add-on is labeled as - <strong>2.3.3</strong>, the newest Google API add-on library for API level 10 adds USB Open - Accessory API support for 2.3.4 devices.</p> - </li> - - <li>Click <strong>Finish</strong>.</li> - - <li>Install the application to your device.</li> - - <li>Connect the ADK board (USB-A) to your Android-powered device (micro-USB). Ensure that the - power cable to the accessory is plugged in or that the micro-USB port on the accesory is - connected to your computer for power (this also allows you to <a href="#monitoring">monitor the - ADK board</a>). When connected, accept the prompt that asks for whether or not to open the - DemoKit application to connect to the accessory. If the prompt does not show up, connect and - reconnect the accessory.</li> - </ol> - - <p>You can now interact with the ADK board by moving the color LED or servo sliders (make sure - the servos are connected) or by pressing the relay buttons in the application. On the ADK shield, - you can press the buttons and move the joystick to see their outputs displayed in the - application.</p> - - <h3 id="monitoring">Monitoring the ADK Board</h3> - - <p>The ADK firmware consists of a few files that you should be looking at if you want to build - your own accessory. The files in the <code>arduino_libs/AndroidAccessory</code> - directory are the most important files and have the logic to detect and connect to - Android-powered devices that support accessory mode. Feel free to add debug statements (Arduino - <code>Serial.println()</code> statements) to the code located in the - <code><arduino_installation_root>/libraries/AndroidAccessory</code> directory and - <code>demokit.pde</code> sketch and re-upload the sketch to the ADK board to - discover more about how the firmware works.</p> - - <p>You can view the debug statements in the Arduino Serial Monitor by clicking <strong>Tools > - Serial Monitor</strong> and setting the baud to 115200. The following sections about how - accessories communicate with Android-powered devices describe much of what you should be doing in - your own accessory.</p> - - <h2 id="accessory-protocol">Implementing the Android Accessory Protocol</h2> - - <p>An Android USB accessory must adhere to Android Accessory Protocol, which defines how - an accessory detects and sets up communication with an Android-powered device. In general, an - accessory should carry out the following steps:</p> - - <ol> - <li>Wait for and detect connected devices</li> - - <li>Determine the device's accessory mode support</li> - - <li>Attempt to start the device in accessory mode if needed</li> - - <li>Establish communication with the device if it supports the Android accessory protocol</li> - </ol> - - <p>The following sections go into depth about how to implement these steps.</p> - - <h3 id="wait">Wait for and detect connected devices</h3> - - <p>Your accessory should have logic to continuously check - for connected Android-powered devices. When a device is connected, your accessory should - determine if the device supports accessory mode.</p> - - <h3 id="determine">Determine the device's accessory mode support</h3> - - - <p>When an Android-powered device is connected, it can be in one of three states:</p> - - <ol type="a"> - <li>The attached device supports Android accessory mode and is already in accessory mode.</li> - - <li>The attached device supports Android accessory mode, but it is not in accessory mode.</li> - - <li>The attached device does not support Android accessory mode.</li> - </ol> - - <p>During the initial connection, the accessory should check the vendor and product IDs of the - connected device's USB device descriptor. The vendor ID should match Google's ID (0x18D1) and the - product ID should be 0x2D00 or 0x2D01 if the device is already in accessory mode (case A). If so, - the accessory can now <a href="#establish">establish communication with the device</a> through - bulk transfer endpoints with its own communication protocol. There is no need to start the device - in accessory mode.</p> - - <p class="note"><strong>Note:</strong> 0x2D00 is reserved for Android-powered devices that - support accessory mode. 0x2D01 is reserved for devices that support accessory mode as well as the - ADB (Android Debug Bridge) protocol, which exposes a second interface with two bulk endpoints for - ADB. You can use these endpoints for debugging the accessory application if you are simulating - the accessory on a computer. In general, do not use this interface unless your accessory is - implementing a passthrough to ADB on the device.</p> - - <p>If the vendor and product ID do not match, there is no way to distinguish between states b and - c, so the accessory <a href="#start">attempts to start the device in accessory mode</a> to figure - out if the device is supported.</p> - - <h3 id="start">Attempt to start the device in accessory mode</h3> - - <p>If the vendor and product IDs do not correspond to an Android-powered device in accessory - mode, the accessory cannot discern whether the device supports accessory mode and is not in that - state, or if the device does not support accessory mode at all. This is because devices that - support accessory mode but aren't in it initially report the device's manufacturer vendor ID and - product ID, and not the special Android Open Accessory ones. In either case, the accessory should try to start - the device into accessory mode to figure out if the device supports it. The following steps - explain how to do this:</p> - - <ol> - <li>Send a 51 control request ("Get Protocol") to figure out if the device supports the Android - accessory protocol. A non-zero number is returned if the protocol is supported, which - represents the version of the protocol that the device supports (currently, only version 1 - exists). This request is a control request on endpoint 0 with the following characteristics: - <pre> -requestType: USB_DIR_IN | USB_TYPE_VENDOR -request: 51 -value: 0 -index: 0 -data: protocol version number (16 bits little endian sent from the device to the accessory) -</pre> - </li> - - <li>If the device returns a proper protocol version, send identifying string information to the - device. This information allows the device to figure out an appropriate application for this - accessory and also present the user with a URL if an appropriate application does not exist. - These requests are control requests on endpoint 0 (for each string ID) with the following - characteristics: - <pre> -requestType: USB_DIR_OUT | USB_TYPE_VENDOR -request: 52 -value: 0 -index: string ID -data zero terminated UTF8 string sent from accessory to device -</pre> - - <p>The following string IDs are supported, with a maximum size of 256 bytes for each string - (must be zero terminated with \0).</p> - <pre> -manufacturer name: 0 -model name: 1 -description: 2 -version: 3 -URI: 4 -serial number: 5 -</pre> - </li> - - <li>When the identifying strings are sent, request the device start up in accessory mode. This - request is a control request on endpoint 0 with the following characteristics: - <pre> -requestType: USB_DIR_OUT | USB_TYPE_VENDOR -request: 53 -value: 0 -index: 0 -data: none -</pre> - </li> - </ol> - - <p>After sending the final control request, the connected USB device should re-introduce itself - on the bus in accessory mode and the accessory can re-enumerate the connected devices. The - algorithm jumps back to <a href="#determine">determining the device's accessory mode support</a> - to check for the vendor and product ID. The vendor ID and product ID of the device will be - different if the device successfully switched to accessory mode and will now correspond to - Google's vendor and product IDs instead of the device manufacturer's IDs. The accessory can now - <a href="#establish">establish communication with the device</a>.</p> - - <p>If at any point these steps fail, the device does not support Android accessory mode and the - accessory should wait for the next device to be connected.</p> - - <h3 id="establish">Establish communication with the device</h3> - - <p>If an Android-powered device in accessory mode is detected, the accessory can query the - device's interface and endpoint descriptors to obtain the bulk endpoints to communicate with the - device. An Android-powered device that has a product ID of 0x2D00 has one interface with two bulk - endpoints for input and output communication. A device with product ID of 0x2D01 has two - interfaces with two bulk endpoints each for input and output communication. The first interface - is for standard communication while the second interface is for ADB communication. To communicate - on an interface, all you need to do is find the first bulk input and output endpoints, set the - device's configuration to a value of 1 with a SET_CONFIGURATION (0x09) device request, then - communicate using the endpoints.</p> - - <h2 id="firmware">How the ADK board implements the Android Accessory protocol</h2> - - <p>If you have access to the ADK board and shield, the following sections describe the firmware - code that you installed onto the ADK board. The firmware demonstrates a practical example of how - to implement the Android Accessory protocol. Even if you do not have the ADK board and shield, - reading through how the hardware detects and interacts with devices in accessory mode is still - useful if you want to port the code over for your own accessories.</p> - - <p>The important pieces of the firmware are the - <code>arduino_libs/AndroidAccessory/examples/demokit/demokit/demokit.pde</code> sketch, which is - the code that receives and sends data to the DemoKit application running on the Android-powered - device. The code to detect and set up communication with the Android-powered device is contained - in the <code>arduino_libs/AndroidAccessory/AndroidAccessory.h</code> and - <code>arduino_libs/AndroidAccessory/AndroidAccessory.cpp</code> files. This code - includes most of the logic that will help you implement your own accessory's firmware. It might - be useful to have all three of these files open in a text editor as you read through these next - sections.</p> - - <p>The following sections describe the firmware code in the context of the algorithm described in - <a href="#accessory-protocol">Implementing the Android Accessory Protocol</a>.</p> - - <h3 id="wait-adk">Wait for and detect connected devices</h3> - - <p>In the firmware code (<code>demokit.pde</code>), the <code>loop()</code> function runs - repeatedly and calls <code>AndroidAccessory::isConnected()</code> to check for any connected - devices. If there is a connected device, it continuously updates the input and output streams - going to and from the board and application. If nothing is connected, it continuously checks for - a device to be connected:</p> - <pre> -... - -AndroidAccessory acc("Google, Inc.", - "DemoKit", - "DemoKit Arduino Board", - "1.0", - "http://www.android.com", - "0000000012345678"); - -... -void loop() -{ -... - if (acc.isConnected()) { - //communicate with Android application - } - else{ - //set the accessory to its default state - } -... -} -</pre> - - <h3 id="determine-adk">Determine the connected device's accessory mode support</h3> - - <p>When a device is connected to the ADK board, it can already be in accessory mode, support - accessory mode and is not in that mode, or does not support accessory mode. The - <code>AndroidAccessory::isConnected()</code> method checks for these cases and responds - accordingly when the <code>loop()</code> function calls it. This function first checks to see if - the device that is connected hasn't already been handled. If not, it gets the connected device's - device descriptor to figure out if the device is already in accessory mode by calling - <code>AndroidAccessory::isAccessoryDevice()</code>. This method checks the vendor and product ID - of the device descriptor. A device in accessory mode has a vendor ID of 0x18D1 and a product ID - of 0x2D00 or 0x2D01. If the device is in accessory mode, then the ADK board can <a href= - "#establish">establish communication with the device</a>. If not, the board <a href= - "#start">attempts to start the device in accessory mode</a>.</p> - <pre> -bool AndroidAccessory::isConnected(void) -{ - USB_DEVICE_DESCRIPTOR *devDesc = (USB_DEVICE_DESCRIPTOR *) descBuff; - byte err; - - max.Task(); - usb.Task(); - - if (!connected && - usb.getUsbTaskState() >= USB_STATE_CONFIGURING && - usb.getUsbTaskState() != USB_STATE_RUNNING) { - Serial.print("\nDevice addressed... "); - Serial.print("Requesting device descriptor."); - - err = usb.getDevDescr(1, 0, 0x12, (char *) devDesc); - if (err) { - Serial.print("\nDevice descriptor cannot be retrieved. Program Halted\n"); - while(1); - } - - if (isAccessoryDevice(devDesc)) { - Serial.print("found android accessory device\n"); - - connected = configureAndroid(); - } else { - Serial.print("found possible device. switching to serial mode\n"); - switchDevice(1); - } - } else if (usb.getUsbTaskState() == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) { - connected = false; - } - - return connected; -} -</pre> - - <h3 id="start-adk">Attempt to start the device in accessory mode</h3> - - <p>If the device is not already in accessory mode, then the ADK board must determine whether or - not it supports it by sending control request 51 to check the version of the USB accessory - protocol that the device supports (see <code>AndroidAccessory::getProtocol()</code>). Protocol - version 1 is the only version for now, but this can be an integer greater than zero in the - future. If the appropriate protocol version is returned, the board sends control request 52 (one - for each string with <code>AndroidAcessory:sendString()</code>) to send it's identifying - information, and tries to start the device in accessory mode with control request 53. The - <code>AndroidAccessory::switchDevice()</code> method takes care of this:</p> - <pre> -bool AndroidAccessory::switchDevice(byte addr) -{ - int protocol = getProtocol(addr); - if (protocol == 1) { - Serial.print("device supports protocol 1\n"); - } else { - Serial.print("could not read device protocol version\n"); - return false; - } - - sendString(addr, ACCESSORY_STRING_MANUFACTURER, manufacturer); - sendString(addr, ACCESSORY_STRING_MODEL, model); - sendString(addr, ACCESSORY_STRING_DESCRIPTION, description); - sendString(addr, ACCESSORY_STRING_VERSION, version); - sendString(addr, ACCESSORY_STRING_URI, uri); - sendString(addr, ACCESSORY_STRING_SERIAL, serial); - - usb.ctrlReq(addr, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE, - ACCESSORY_START, 0, 0, 0, 0, NULL); - return true; -} -</pre>If this method returns false, the board waits until a new device is connected. If it is -successful, the device displays itself on the USB bus as being in accessory mode when the ADK board -re-enumerates the bus. When the device is in accessory mode, the accessory then <a href= -"#establish-adk">establishes communication with the device</a>. - - <h3 id="establish-adk">Establish communication with the device</h3> - - <p>If a device is detected as being in accessory mode, the accessory must find the proper bulk - endpoints and set up communication with the device. When the ADK board detects an Android-powered - device in accessory mode, it calls the <code>AndroidAccessory::configureAndroid()</code> - function:</p> - <pre> -... -if (isAccessoryDevice(devDesc)) { - Serial.print("found android acessory device\n"); - - connected = configureAndroid(); - } -... -</pre> - - <p>which in turn calls the <code>findEndpoints()</code> function:</p> - <pre> -... -bool AndroidAccessory::configureAndroid(void) -{ - byte err; - EP_RECORD inEp, outEp; - - if (!findEndpoints(1, &inEp, &outEp)) - return false; -... -</pre> - - <p>The <code>AndroidAccessory::findEndpoints()</code> function queries the Android-powered - device's configuration descriptor and finds the bulk data endpoints in which to communicate with - the USB device. To do this, it first gets the device's first four bytes of the configuration - descriptor (only need descBuff[2] and descBuff[3]), which contains the information about the - total length of data returned by getting the descriptor. This data is used to determine whether - or not the descriptor can fit in the descriptor buffer. This descriptor also contains information - about all the interfaces and endpoint descriptors. If the descriptor is of appropriate size, the - method reads the entire configuration descriptor and fills the entire descriptor buffer with this - device's configuration descriptor. If for some reason the descriptor is no longer attainable, an - error is returned.</p> - <pre> -... - -bool AndroidAccessory::findEndpoints(byte addr, EP_RECORD *inEp, EP_RECORD *outEp) -{ - int len; - byte err; - uint8_t *p; - - err = usb.getConfDescr(addr, 0, 4, 0, (char *)descBuff); - if (err) { - Serial.print("Can't get config descriptor length\n"); - return false; - } - - - len = descBuff[2] | ((int)descBuff[3] << 8); - if (len > sizeof(descBuff)) { - Serial.print("config descriptor too large\n"); - /* might want to truncate here */ - return false; - } - - err = usb.getConfDescr(addr, 0, len, 0, (char *)descBuff); - if (err) { - Serial.print("Can't get config descriptor\n"); - return false; - } - -... -</pre> - - <p>Once the descriptor is in memory, a pointer is assigned to the first position of the buffer - and is used to index the buffer for reading. There are two endpoint pointers (input and output) - that are passed into <code>AndroidAccessory::findEndpoints()</code> and their addresses are set - to 0, because the code hasn't found any suitable bulk endpoints yet. A loop reads the buffer, - parsing each configuration, interface, or endpoint descriptor. For each descriptor, Position 0 - always contains the size of the descriptor in bytes and position 1 always contains the descriptor - type. Using these two values, the loop skips any configuration and interface descriptors and - increments the buffer with the <code>descLen</code> variable to get to the next descriptor.</p> - - <p class="note"><strong>Note:</strong> An Android-powered device in accessory mode can - potentially have two interfaces, one for the default communication to the device and the other - for ADB communication. The default communication interface is always indexed first, so finding - the first input and output bulk endpoints will return the default communication endpoints, which - is what the <code>demokit.pde</code> sketch does. If you are writing your own firmware, the logic - to find the appropriate endpoints for your accessory might be different.</p> - - <p>When it finds the first input and output endpoint descriptors, it sets the endpoint pointers - to those addresses. If the findEndpoints() function finds both an input and output endpoint, it - returns true. It ignores any other endpoints that it finds (the endpoints for the ADB interface, - if present).</p> - <pre> -... - p = descBuff; - inEp->epAddr = 0; - outEp->epAddr = 0; - while (p < (descBuff + len)){ - uint8_t descLen = p[0]; - uint8_t descType = p[1]; - USB_ENDPOINT_DESCRIPTOR *epDesc; - EP_RECORD *ep; - - switch (descType) { - case USB_DESCRIPTOR_CONFIGURATION: - Serial.print("config desc\n"); - break; - - case USB_DESCRIPTOR_INTERFACE: - Serial.print("interface desc\n"); - break; - - case USB_DESCRIPTOR_ENDPOINT: - epDesc = (USB_ENDPOINT_DESCRIPTOR *)p; - if (!inEp->epAddr && (epDesc->bEndpointAddress & 0x80)) - ep = inEp; - else if (!outEp->epAddr) - ep = outEp; - else - ep = NULL; - - if (ep) { - ep->epAddr = epDesc->bEndpointAddress & 0x7f; - ep->Attr = epDesc->bmAttributes; - ep->MaxPktSize = epDesc->wMaxPacketSize; - ep->sndToggle = bmSNDTOG0; - ep->rcvToggle = bmRCVTOG0; - } - break; - - default: - Serial.print("unkown desc type "); - Serial.println( descType, HEX); - break; - } - - p += descLen; - } - - if (!(inEp->epAddr && outEp->epAddr)) - Serial.println("can't find accessory endpoints"); - - return inEp->epAddr && outEp->epAddr; -} - -... -</pre> - - <p>Back in the <code>configureAndroid()</code> function, if there were endpoints found, they are - appropriately set up for communication. The device's configuration is set to 1 and the state of - the device is set to "running", which signifies that the device is properly set up to communicate - with your USB accessory. Setting this status prevents the device from being re-detected and - re-configured in the <code>AndroidAccessory::isConnected()</code> function.</p> - <pre> -bool AndroidAccessory::configureAndroid(void) -{ - byte err; - EP_RECORD inEp, outEp; - - if (!findEndpoints(1, &inEp, &outEp)) - return false; - - memset(&epRecord, 0x0, sizeof(epRecord)); - - epRecord[inEp.epAddr] = inEp; - if (outEp.epAddr != inEp.epAddr) - epRecord[outEp.epAddr] = outEp; - - in = inEp.epAddr; - out = outEp.epAddr; - - Serial.print("inEp: "); - Serial.println(inEp.epAddr, HEX); - Serial.print("outEp: "); - Serial.println(outEp.epAddr, HEX); - - epRecord[0] = *(usb.getDevTableEntry(0,0)); - usb.setDevTableEntry(1, epRecord); - - err = usb.setConf( 1, 0, 1 ); - if (err) { - Serial.print("Can't set config to 1\n"); - return false; - } - - usb.setUsbTaskState( USB_STATE_RUNNING ); - - return true; -} -</pre> - - <p>Lastly, methods to read and write to the appropriate endpoints are needed. The - <code>demokit.pde</code> sketch calls these methods depending on the data that is read from the - Android-powered device or sent by the ADK board. For instance, moving the joystick on the ADK - shield writes data that is read by the DemoKit application running on the Android-powered device. - Moving sliders on the DemoKit application is read by the <code>demokit.pde</code> sketch and - changes the state of the accessory, such as lighting up or changing the color of the LED - lights.</p> - <pre> -int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit) { - return usb.newInTransfer(1, in, len, (char *)buff, nakLimit); } - -int AndroidAccessory::write(void *buff, int len) { - usb.outTransfer(1, out, len, (char *)buff); - return len; } -</pre> - - <p>See the <code>demokit.pde</code> sketch for information about how the ADK board - reads and writes data.</p> |