From 4d86bd32a627a0e3bcbe4536151ff16590b2dd68 Mon Sep 17 00:00:00 2001 From: Robert Ly Date: Tue, 3 May 2011 01:47:09 -0700 Subject: Doc change: adding ADK doc. still need to add the adk pkg download link when we get the package Change-Id: I941e708a70b48dba2da4aa3d186824c89ebfb22f --- docs/html/guide/guide_toc.cs | 1 + docs/html/guide/topics/usb/adk.jd | 763 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 764 insertions(+) create mode 100644 docs/html/guide/topics/usb/adk.jd (limited to 'docs/html/guide') diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 35acdd7..2f7c60c 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -304,6 +304,7 @@ diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd new file mode 100644 index 0000000..c0a0f27 --- /dev/null +++ b/docs/html/guide/topics/usb/adk.jd @@ -0,0 +1,763 @@ +page.title=Android Open Accessory Development Kit +@jd:body + +
+ +
+ +

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 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 + initiate the connection.

+ +

Note: 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 <uses-feature> + element in your corresponding application's Android manifest. For more information, see the USB Accessory Developer + Guide.

+ +

The Android Open Accessory Development Kit (ADK) provides an implementation of an Android USB accessory that is based on the + Arduino open source electronics prototyping platform, 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 code are contained in the ADK package download. + You can buy the hardware components of the ADK if you do not already have them. + The main hardware and software components of the ADK include:

+ + + +

Getting Started with the ADK

+ +

The following sections describe how to install the Arduino software on your computer, use the Arduino software + 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:

+ + + +

Installing the Arduino software and necessary libraries

+

To install the Arduino software:

+
    +
  1. Download and install the Arduino Software + as described on the Arduino website. + +

    Note: 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.

    +
  2. + +
  3. Download and extract the ADK package to a directory of your choice. You should have + an app, firmware, and hardware directories.
  4. + +
  5. Extract the CapSense download to a directory of your choice.
  6. + +
  7. Install the necessary libraries: +

    On Windows:

    +
      +
    1. Copy the firmware/arduino_libs/AndroidAccessory and + firmware/arduino_libs/USB_Host_Shield directories (the complete directories, + not just the files within) to the <arduino_installation_root>/libraries/ + directory.
    2. + +
    3. Create a CapSense directory in the + <arduino_installation_root>/libraries/ directory
    4. + +
    5. Copy CapSense.cpp and CapSense.h from the unzipped CapSense + download to the CapSense directory.
    6. +
    + +

    On Mac:

    +
      +
    1. Right-click on the Arduino application in Finder and select Show Package + Contents.
    2. + +
    3. Copy the firmware/arduino_libs/AndroidAccessory and + firmware/arduino_libs/USB_Host_Shield directories (the complete directories, + not just the files within) to the Contents/Resources/Java/libraries + directory inside the Arduino application.
    4. + +
    5. Create a CapSense directory in the + Contents/Resources/Java/libraries directory.
    6. + +
    7. Copy CapSense.cpp and CapSense.h from the unzipped CapSense + download to the CapSense directory.
    8. + +
    + +

    On Linux (Ubuntu):

    +
      +
    1. Copy the firmware/arduino_libs/AndroidAccessory and + firmware/arduino_libs/USB_Host_Shield directories (the complete directories, + not just the files within) to the <arduino_installation_root>/libraries/ directory.
    2. + +
    3. Create a CapSense directory in the + <arduino_installation_root>/libraries/ directory.
    4. + +
    5. Copy CapSense.cpp and CapSense.h from the unzipped CapSense + download to the CapSense directory.
    6. + +
    7. Install the avr-libc library by entering sudo apt-get install avr-libc from a shell prompt.
    8. +
    + +
  8. +
+

You should now have three new directories in the Arduino libraries directory: + AndroidAccessory, USB_Host_Shield, and CapSense.

+ +

Installing the firmware to the ADK board

+

To install the firmware to the ADK board:

+
    +
  1. Connect the ADK board to your computer using the micro-USB port, which allows two-way communication and provides power to the ADK board.
  2. + +
  3. Launch Arduino.
  4. + +
  5. Click Tools > Board > Arduino Mega 2560 to specify the ADK board's type.
  6. + +
  7. Select the appropriate USB port: +
      +
    • On Windows: click Tools > Serial Port > COM# 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.
    • + +
    • On Mac: Click Tools > Serial Port > dev/tty.usbserial-### to specify the + port of communication.
    • + +
    • On Linux (Ubuntu): Click Tools > Serial Port > dev/ttyUSB# to specify the + port of communication.
    • +
  8. + +
  9. To open the firmware code (a sketch), click File > Open and select + firmware/demokit/demokit.pde.
  10. + +
  11. Click Sketch > Compile/Verify to ensure that the sketch has no + errors.
  12. + +
  13. Select File > Upload to I/O Board. When Arduino outputs Done uploading., the board + is ready to communicate with your Android-powered device.
  14. + +
+ + +

Running the DemoKit Android application

+ +

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.

+ +

To install and run the application in Eclipse:

+ +
    +
  1. Install the Google APIs API Level 10 add-on library, + 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 USB Accessory documentation.
  2. +
  3. Click File > New > Project..., then select Android > Android Project
  4. +
  5. In the Project name: field, type DemoKit. +
  6. Choose Create project from existing source, click Browse, select the + app directory, and click Finish.
  7. + +
  8. For Build Target, select Google APIs (Platform 2.3.3, API Level 10). +

    Note: Even though the add-on is labeled as + 2.3.3, the newest Google API add-on library for API level 10 adds + USB Open Accessory API support for 2.3.4 devices.

  9. + +
  10. Click Finish.
  11. +
  12. Install the application to your device.
  13. + +
  14. 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 monitor the ADK board). 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.
  15. +
+

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.

+ +

Monitoring the ADK Board

+

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 firmware/arduino_libs/AndroidAccessory 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 Serial.print() statements) to the code located in the +arduino_libraries_directory/AndroidAccessory directory and firmware/demokit/demokit.pde sketch and re-upload the sketch to the ADK board to discover more +about how the firmware works.

+ +

You can view the debug statements in the Arduino Serial Monitor by clicking +Tools > Serial Monitor 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.

+

+ +

How an Accessory Communicates with an Android-powered Device in Accessory Mode

+ +

When you connect an accessory to an Android-powered device, the accessory's firmware must + carry out some standard steps to set up communication with the Android-powered device. If you are building an + accessory along with an application, this section goes over some general steps that your firmware + should carry out.

+ +

In general, an accessory should carry out the following steps:

+ +
    +
  1. Wait for and detect connected devices
  2. + +
  3. Determine the device's accessory mode support
  4. + +
  5. Attempt to start the device in accessory mode if needed
  6. + +
  7. Establish communication with the device if it supports the Android accessory protocol
  8. +
+ +

Wait for and detect connected devices

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.

+ +

Determine the device's accessory mode support

+

When an Android-powered device is connected, it can be in one of three states:

+ +
    + +
  1. The attached device supports Android accessory mode and is already in accessory mode.
  2. +
  3. The attached device supports Android accessory mode, but it is not in accessory mode.
  4. +
  5. The attached device does not support Android accessory mode.
  6. + + +
+ +

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 establish communication with the device through bulk transfer endpoints with its + own communication protocol. There is no need to start the device in accessory mode.

+ +

Note: 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.

+ +

If the vendor and product ID do not match, there is no way to distinguish between states b and + c, so the accessory attempts to start the device in accessory mode to + figure out if the device is supported.

+ +

Attempt to start the device in accessory mode

+ +

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 Google 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:

+ +
    +
  1. 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: +
    +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)
    +
    +
  2. + +
  3. 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: +
    +requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
    +request:        52
    +value:          0
    +index:          string ID
    +data            zero terminated UTF8 string sent from accessory to device
    +
    + +

    The following string IDs are supported, with a maximum size of 256 bytes for each string (must + be zero terminated with \0).

    +
    +manufacturer name:  1
    +model name:         2
    +description:        3
    +version:            4
    +URI:                5
    +serial number:      6
    +
    +
  4. + +
  5. 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: +
    +requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
    +request:        53
    +value:          0
    +index:          0
    +data:           none
    +
    +
  6. +
+

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 + determining the device's accessory mode support 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 establish communication with the device.

+ +

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.

+ + +

Establish communication with the device

+ +

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.

+ + + +

How the ADK board communicates with an Android-powered Device in Accessory Mode

+ +

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 communicate with an Android-powered device. 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.

+ +

The important pieces of the firmware are the accessory/demokit/demokit/demokit.pde 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 + accessory/arduino_libs/AndroidAccessory/AndroidAccessory.h and accessory/arduino_libs/AndroidAccessory/AndroidAccessory.cpp + 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.

+ +

The following sections describe the firmware code in the context of the + algorithm described in How an Accessory Communicates with an Android-powered + Device in Accessory Mode.

+ +

Wait for and detect connected devices

+ +

In the firmware code (demokit.pde), the + loop() function runs repeatedly and calls + AndroidAccessory::isConnected() 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:

+
+...
+
+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
+    }
+...
+}
+
+ +

Determine the connected device's accessory mode support

+ +

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 + AndroidAccessory::isConnected() method checks for these cases and responds + accordingly when the loop() 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 + AndroidAccessory::isAccessoryDevice(). 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 + establish communication with the device. If not, the board attempts to start the device in accessory mode.

+
+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;
+}
+
+ +

Attempt to start the device in accessory mode

+ +

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 + AndroidAccessory::getProtocol()). 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 AndroidAcessory:sendString()) to send it's identifying information, and + tries to start the device in accessory mode with control request 53. The + AndroidAccessory::switchDevice() method takes care of this:

+
+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;
+}
+
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 establishes communication with the device. + +

Establish communication with the device

+ +

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 + AndroidAccessory::configureAndroid() function:

+
+...
+if (isAccessoryDevice(devDesc)) {
+            Serial.print("found android acessory device\n");
+
+            connected = configureAndroid();
+        }
+...
+
+ +

which in turn calls the findEndpoints() function:

+
+...
+bool AndroidAccessory::configureAndroid(void)
+{
+    byte err;
+    EP_RECORD inEp, outEp;
+
+    if (!findEndpoints(1, &inEp, &outEp))
+        return false;
+...
+
+ +

The AndroidAccessory::findEndpoints() 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.

+
+...
+
+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;
+    }
+    
+...
+
+ +

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 AndroidAccessory::findEndpoints() 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 descLen variable to get to the next + descriptor.

+ +

Note: 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 demokit.pde sketch does. If you are writing your own firmware, the logic + to find the appropriate endpoints for your accessory might be different.

+ +

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 = 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;
+}
+
+...
+
+ +

Back in the configureAndroid() 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 + AndroidAccessory::isConnected() function.

+
+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;
+}
+
+ +

Lastly, methods to read and write to the appropriate endpoints are needed. The + demokit.pde 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 + demokit.pde sketch and changes the state of the accessory, such as lighting up or + changing the color of the LED lights.

+
+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; }
+  
+
+ +

See the firmware/demokit/demokit.pde file for information about how the Demo Shield reads and writes data.

-- cgit v1.1