Home | History | Annotate | Download | only in AndroidAccessory
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 #include <Max3421e.h>
     19 #include <Usb.h>
     20 #include <AndroidAccessory.h>
     21 
     22 #define USB_ACCESSORY_VENDOR_ID         0x18D1
     23 #define USB_ACCESSORY_PRODUCT_ID        0x2D00
     24 
     25 #define USB_ACCESSORY_ADB_PRODUCT_ID    0x2D01
     26 #define ACCESSORY_STRING_MANUFACTURER   0
     27 #define ACCESSORY_STRING_MODEL          1
     28 #define ACCESSORY_STRING_DESCRIPTION    2
     29 #define ACCESSORY_STRING_VERSION        3
     30 #define ACCESSORY_STRING_URI            4
     31 #define ACCESSORY_STRING_SERIAL         5
     32 
     33 #define ACCESSORY_GET_PROTOCOL          51
     34 #define ACCESSORY_SEND_STRING           52
     35 #define ACCESSORY_START                 53
     36 
     37 
     38 AndroidAccessory::AndroidAccessory(const char *manufacturer,
     39                                    const char *model,
     40                                    const char *description,
     41                                    const char *version,
     42                                    const char *uri,
     43                                    const char *serial) : manufacturer(manufacturer),
     44                                                          model(model),
     45                                                          description(description),
     46                                                          version(version),
     47                                                          uri(uri),
     48                                                          serial(serial),
     49                                                          connected(false)
     50 {
     51 
     52 }
     53 
     54 void AndroidAccessory::powerOn(void)
     55 {
     56     max.powerOn();
     57     delay(200);
     58 }
     59 
     60 int AndroidAccessory::getProtocol(byte addr)
     61 {
     62     uint16_t protocol = -1;
     63     usb.ctrlReq(addr, 0,
     64                 USB_SETUP_DEVICE_TO_HOST |
     65                 USB_SETUP_TYPE_VENDOR |
     66                 USB_SETUP_RECIPIENT_DEVICE,
     67                 ACCESSORY_GET_PROTOCOL, 0, 0, 0, 2, (char *)&protocol);
     68     return protocol;
     69 }
     70 
     71 void AndroidAccessory::sendString(byte addr, int index, const char *str)
     72 {
     73     usb.ctrlReq(addr, 0,
     74                 USB_SETUP_HOST_TO_DEVICE |
     75                 USB_SETUP_TYPE_VENDOR |
     76                 USB_SETUP_RECIPIENT_DEVICE,
     77                 ACCESSORY_SEND_STRING, 0, 0, index,
     78                 strlen(str) + 1, (char *)str);
     79 }
     80 
     81 
     82 bool AndroidAccessory::switchDevice(byte addr)
     83 {
     84     int protocol = getProtocol(addr);
     85 
     86     if (protocol >= 1) {
     87         Serial.print("device supports protocol 1 or higher\n");
     88     } else {
     89         Serial.print("could not read device protocol version\n");
     90         return false;
     91     }
     92 
     93     sendString(addr, ACCESSORY_STRING_MANUFACTURER, manufacturer);
     94     sendString(addr, ACCESSORY_STRING_MODEL, model);
     95     sendString(addr, ACCESSORY_STRING_DESCRIPTION, description);
     96     sendString(addr, ACCESSORY_STRING_VERSION, version);
     97     sendString(addr, ACCESSORY_STRING_URI, uri);
     98     sendString(addr, ACCESSORY_STRING_SERIAL, serial);
     99 
    100     usb.ctrlReq(addr, 0,
    101                 USB_SETUP_HOST_TO_DEVICE |
    102                 USB_SETUP_TYPE_VENDOR |
    103                 USB_SETUP_RECIPIENT_DEVICE,
    104                 ACCESSORY_START, 0, 0, 0, 0, NULL);
    105 
    106     while (usb.getUsbTaskState() != USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) {
    107         max.Task();
    108         usb.Task();
    109     }
    110 
    111     return true;
    112 }
    113 
    114 // Finds the first bulk IN and bulk OUT endpoints
    115 bool AndroidAccessory::findEndpoints(byte addr, EP_RECORD *inEp, EP_RECORD *outEp)
    116 {
    117     int len;
    118     byte err;
    119     uint8_t *p;
    120 
    121     err = usb.getConfDescr(addr, 0, 4, 0, (char *)descBuff);
    122     if (err) {
    123         Serial.print("Can't get config descriptor length\n");
    124         return false;
    125     }
    126 
    127 
    128     len = descBuff[2] | ((int)descBuff[3] << 8);
    129     if (len > sizeof(descBuff)) {
    130         Serial.print("config descriptor too large\n");
    131             /* might want to truncate here */
    132         return false;
    133     }
    134 
    135     err = usb.getConfDescr(addr, 0, len, 0, (char *)descBuff);
    136     if (err) {
    137         Serial.print("Can't get config descriptor\n");
    138         return false;
    139     }
    140 
    141     p = descBuff;
    142     inEp->epAddr = 0;
    143     outEp->epAddr = 0;
    144     while (p < (descBuff + len)){
    145         uint8_t descLen = p[0];
    146         uint8_t descType = p[1];
    147         USB_ENDPOINT_DESCRIPTOR *epDesc;
    148         EP_RECORD *ep;
    149 
    150         switch (descType) {
    151         case USB_DESCRIPTOR_CONFIGURATION:
    152             Serial.print("config desc\n");
    153             break;
    154 
    155         case USB_DESCRIPTOR_INTERFACE:
    156             Serial.print("interface desc\n");
    157             break;
    158 
    159         case USB_DESCRIPTOR_ENDPOINT:
    160             epDesc = (USB_ENDPOINT_DESCRIPTOR *)p;
    161             if (!inEp->epAddr && (epDesc->bEndpointAddress & 0x80))
    162                 ep = inEp;
    163             else if (!outEp->epAddr)
    164                 ep = outEp;
    165             else
    166                 ep = NULL;
    167 
    168             if (ep) {
    169                 ep->epAddr = epDesc->bEndpointAddress & 0x7f;
    170                 ep->Attr = epDesc->bmAttributes;
    171                 ep->MaxPktSize = epDesc->wMaxPacketSize;
    172                 ep->sndToggle = bmSNDTOG0;
    173                 ep->rcvToggle = bmRCVTOG0;
    174             }
    175             break;
    176 
    177         default:
    178             Serial.print("unkown desc type ");
    179             Serial.println( descType, HEX);
    180             break;
    181         }
    182 
    183         p += descLen;
    184     }
    185 
    186     if (!(inEp->epAddr && outEp->epAddr))
    187         Serial.println("can't find accessory endpoints");
    188 
    189     return inEp->epAddr && outEp->epAddr;
    190 }
    191 
    192 bool AndroidAccessory::configureAndroid(void)
    193 {
    194     byte err;
    195     EP_RECORD inEp, outEp;
    196 
    197     if (!findEndpoints(1, &inEp, &outEp))
    198         return false;
    199 
    200     memset(&epRecord, 0x0, sizeof(epRecord));
    201 
    202     epRecord[inEp.epAddr] = inEp;
    203     if (outEp.epAddr != inEp.epAddr)
    204         epRecord[outEp.epAddr] = outEp;
    205 
    206     in = inEp.epAddr;
    207     out = outEp.epAddr;
    208 
    209     Serial.println(inEp.epAddr, HEX);
    210     Serial.println(outEp.epAddr, HEX);
    211 
    212     epRecord[0] = *(usb.getDevTableEntry(0,0));
    213     usb.setDevTableEntry(1, epRecord);
    214 
    215     err = usb.setConf( 1, 0, 1 );
    216     if (err) {
    217         Serial.print("Can't set config to 1\n");
    218         return false;
    219     }
    220 
    221     usb.setUsbTaskState( USB_STATE_RUNNING );
    222 
    223     return true;
    224 }
    225 
    226 bool AndroidAccessory::isConnected(void)
    227 {
    228     USB_DEVICE_DESCRIPTOR *devDesc = (USB_DEVICE_DESCRIPTOR *) descBuff;
    229     byte err;
    230 
    231     max.Task();
    232     usb.Task();
    233 
    234     if (!connected &&
    235         usb.getUsbTaskState() >= USB_STATE_CONFIGURING &&
    236         usb.getUsbTaskState() != USB_STATE_RUNNING) {
    237         Serial.print("\nDevice addressed... ");
    238         Serial.print("Requesting device descriptor.\n");
    239 
    240         err = usb.getDevDescr(1, 0, 0x12, (char *) devDesc);
    241         if (err) {
    242             Serial.print("\nDevice descriptor cannot be retrieved. Trying again\n");
    243             return false;
    244         }
    245 
    246         if (isAccessoryDevice(devDesc)) {
    247             Serial.print("found android acessory device\n");
    248 
    249             connected = configureAndroid();
    250         } else {
    251             Serial.print("found possible device. swithcing to serial mode\n");
    252             switchDevice(1);
    253         }
    254     } else if (usb.getUsbTaskState() == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) {
    255         if (connected)
    256             Serial.println("disconnect\n");
    257         connected = false;
    258     }
    259 
    260     return connected;
    261 }
    262 
    263 int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit)
    264 {
    265     return usb.newInTransfer(1, in, len, (char *)buff, nakLimit);
    266 }
    267 
    268 int AndroidAccessory::write(void *buff, int len)
    269 {
    270     usb.outTransfer(1, out, len, (char *)buff);
    271     return len;
    272 }
    273 
    274