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