Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UsbHostMAX3421E_Hello
adk.cpp
00001 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. 00002 00003 This software may be distributed and modified under the terms of the GNU 00004 General Public License version 2 (GPL2) as published by the Free Software 00005 Foundation and appearing in the file GPL2.TXT included in the packaging of 00006 this file. Please note that GPL2 Section 2[b] requires that all works based 00007 on this software must also be made publicly available under the terms of 00008 the GPL2 ("Copyleft"). 00009 00010 Contact information 00011 ------------------- 00012 00013 Circuits At Home, LTD 00014 Web : http://www.circuitsathome.com 00015 e-mail : support@circuitsathome.com 00016 */ 00017 00018 /* Google ADK interface */ 00019 00020 #include "adk.h" 00021 00022 const uint8_t ADK::epDataInIndex = 1; 00023 const uint8_t ADK::epDataOutIndex = 2; 00024 00025 ADK::ADK(Usb *p, const char* manufacturer, 00026 const char* model, 00027 const char* description, 00028 const char* version, 00029 const char* uri, 00030 const char* serial) : 00031 00032 /* ADK ID Strings */ 00033 manufacturer(manufacturer), 00034 model(model), 00035 description(description), 00036 version(version), 00037 uri(uri), 00038 serial(serial), 00039 pUsb(p), //pointer to USB class instance - mandatory 00040 bAddress(0), //device address - mandatory 00041 bConfNum(0), //configuration number 00042 bNumEP(1), //if config descriptor needs to be parsed 00043 ready(false) { 00044 // initialize endpoint data structures 00045 for(uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) { 00046 epInfo[i].epAddr = 0; 00047 epInfo[i].maxPktSize = (i) ? 0 : 8; 00048 epInfo[i].bmSndToggle = 0; 00049 epInfo[i].bmRcvToggle = 0; 00050 epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; 00051 }//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++... 00052 00053 // register in USB subsystem 00054 if(pUsb) { 00055 pUsb->RegisterDeviceClass(this); //set devConfig[] entry 00056 } 00057 } 00058 00059 uint8_t ADK::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { 00060 return Init(parent, port, lowspeed); // Just call Init. Yes, really! 00061 } 00062 00063 /* Connection initialization of an Android phone */ 00064 uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) { 00065 uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; 00066 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf); 00067 uint8_t rcode; 00068 uint8_t num_of_conf; // number of configurations 00069 UsbDevice *p = NULL; 00070 EpInfo *oldep_ptr = NULL; 00071 00072 // get memory address of USB device address pool 00073 AddressPool &addrPool = pUsb->GetAddressPool(); 00074 00075 USBTRACE("\r\nADK Init"); 00076 00077 // check if address has already been assigned to an instance 00078 if(bAddress) { 00079 USBTRACE("\r\nAddress in use"); 00080 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; 00081 } 00082 00083 // Get pointer to pseudo device with address 0 assigned 00084 p = addrPool.GetUsbDevicePtr(0); 00085 00086 if(!p) { 00087 USBTRACE("\r\nAddress not found"); 00088 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00089 } 00090 00091 if(!p->epinfo) { 00092 USBTRACE("epinfo is null\r\n"); 00093 return USB_ERROR_EPINFO_IS_NULL; 00094 } 00095 00096 // Save old pointer to EP_RECORD of address 0 00097 oldep_ptr = p->epinfo; 00098 00099 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence 00100 p->epinfo = epInfo; 00101 00102 p->lowspeed = lowspeed; 00103 00104 // Get device descriptor 00105 rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); 00106 00107 // Restore p->epinfo 00108 p->epinfo = oldep_ptr; 00109 00110 if(rcode) { 00111 goto FailGetDevDescr; 00112 } 00113 00114 // Allocate new address according to device class 00115 bAddress = addrPool.AllocAddress(parent, false, port); 00116 00117 // Extract Max Packet Size from device descriptor 00118 epInfo[0].maxPktSize = udd->bMaxPacketSize0; 00119 00120 // Assign new address to the device 00121 rcode = pUsb->setAddr(0, 0, bAddress); 00122 if(rcode) { 00123 p->lowspeed = false; 00124 addrPool.FreeAddress(bAddress); 00125 bAddress = 0; 00126 //USBTRACE2("setAddr:",rcode); 00127 return rcode; 00128 }//if (rcode... 00129 00130 //USBTRACE2("\r\nAddr:", bAddress); 00131 // Spec says you should wait at least 200ms. 00132 //wait_ms(300); 00133 00134 p->lowspeed = false; 00135 00136 //get pointer to assigned address record 00137 p = addrPool.GetUsbDevicePtr(bAddress); 00138 if(!p) { 00139 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00140 } 00141 00142 p->lowspeed = lowspeed; 00143 00144 // Assign epInfo to epinfo pointer - only EP0 is known 00145 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); 00146 if(rcode) { 00147 goto FailSetDevTblEntry; 00148 } 00149 00150 //check if ADK device is already in accessory mode; if yes, configure and exit 00151 if(udd->idVendor == ADK_VID && 00152 (udd->idProduct == ADK_PID || udd->idProduct == ADB_PID)) { 00153 USBTRACE("\r\nAcc.mode device detected"); 00154 /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */ 00155 num_of_conf = udd->bNumConfigurations; 00156 00157 //USBTRACE2("\r\nNC:",num_of_conf); 00158 for(uint8_t i = 0; i < num_of_conf; i++) { 00159 ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this); 00160 wait_ms(1); 00161 rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); 00162 #if defined(XOOM) 00163 //added by Jaylen Scott Vanorden 00164 if(rcode) { 00165 USBTRACE2("\r\nGot 1st bad code for config: ", rcode); 00166 // Try once more 00167 rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); 00168 } 00169 #endif 00170 if(rcode) { 00171 goto FailGetConfDescr; 00172 } 00173 if(bNumEP > 2) { 00174 break; 00175 } 00176 } // for (uint8_t i=0; i<num_of_conf; i++... 00177 00178 if(bNumEP == 3) { 00179 // Assign epInfo to epinfo pointer - this time all 3 endpoins 00180 rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); 00181 if(rcode) { 00182 goto FailSetDevTblEntry; 00183 } 00184 } 00185 00186 // Set Configuration Value 00187 rcode = pUsb->setConf(bAddress, 0, bConfNum); 00188 if(rcode) { 00189 goto FailSetConfDescr; 00190 } 00191 /* print endpoint structure */ 00192 /* 00193 USBTRACE("\r\nEndpoint Structure:"); 00194 USBTRACE("\r\nEP0:"); 00195 USBTRACE2("\r\nAddr: ", epInfo[0].epAddr); 00196 USBTRACE2("\r\nMax.pkt.size: ", epInfo[0].maxPktSize); 00197 USBTRACE2("\r\nAttr: ", epInfo[0].epAttribs); 00198 USBTRACE("\r\nEpout:"); 00199 USBTRACE2("\r\nAddr: ", epInfo[epDataOutIndex].epAddr); 00200 USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataOutIndex].maxPktSize); 00201 USBTRACE2("\r\nAttr: ", epInfo[epDataOutIndex].epAttribs); 00202 USBTRACE("\r\nEpin:"); 00203 USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr); 00204 USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize); 00205 USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs); 00206 */ 00207 00208 USBTRACE("\r\nConfiguration successful"); 00209 ready = true; 00210 return 0; //successful configuration 00211 }//if( buf->idVendor == ADK_VID... 00212 00213 //probe device - get accessory protocol revision 00214 { 00215 uint16_t adkproto = -1; 00216 wait_ms(1); 00217 rcode = getProto((uint8_t*) & adkproto); 00218 #if defined(XOOM) 00219 //added by Jaylen Scott Vanorden 00220 if(rcode) { 00221 USBTRACE2("\r\nGot 1st bad code for proto: ", rcode); 00222 // Try once more 00223 rcode = getProto((uint8_t*) & adkproto); 00224 } 00225 #endif 00226 if(rcode) { 00227 goto FailGetProto; //init fails 00228 } 00229 USBTRACE2("\r\nADK protocol rev. ", adkproto); 00230 } 00231 00232 wait_ms(100); 00233 00234 //sending ID strings 00235 sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer); 00236 wait_ms(10); 00237 sendStr(ACCESSORY_STRING_MODEL, model); 00238 wait_ms(10); 00239 sendStr(ACCESSORY_STRING_DESCRIPTION, description); 00240 wait_ms(10); 00241 sendStr(ACCESSORY_STRING_VERSION, version); 00242 wait_ms(10); 00243 sendStr(ACCESSORY_STRING_URI, uri); 00244 wait_ms(10); 00245 sendStr(ACCESSORY_STRING_SERIAL, serial); 00246 00247 wait_ms(100); 00248 00249 //switch to accessory mode 00250 //the Android phone will reset 00251 rcode = switchAcc(); 00252 if(rcode) { 00253 goto FailSwAcc; //init fails 00254 } 00255 rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; 00256 wait_ms(100); // Give Android a chance to do its reset. This is a guess, and possibly could be lower. 00257 goto SwAttempt; //switch to accessory mode attempted 00258 00259 /* diagnostic messages */ 00260 FailGetDevDescr: 00261 #ifdef DEBUG_USB_HOST 00262 NotifyFailGetDevDescr(rcode); 00263 goto Fail; 00264 #endif 00265 00266 FailSetDevTblEntry: 00267 #ifdef DEBUG_USB_HOST 00268 NotifyFailSetDevTblEntry(rcode); 00269 goto Fail; 00270 #endif 00271 00272 FailGetConfDescr: 00273 #ifdef DEBUG_USB_HOST 00274 NotifyFailGetConfDescr(rcode); 00275 goto Fail; 00276 #endif 00277 00278 FailSetConfDescr: 00279 #ifdef DEBUG_USB_HOST 00280 NotifyFailSetConfDescr(rcode); 00281 goto Fail; 00282 #endif 00283 00284 FailGetProto: 00285 #ifdef DEBUG_USB_HOST 00286 USBTRACE("\r\ngetProto:"); 00287 goto Fail; 00288 #endif 00289 00290 FailSwAcc: 00291 #ifdef DEBUG_USB_HOST 00292 USBTRACE("\r\nswAcc:"); 00293 goto Fail; 00294 #endif 00295 00296 //FailOnInit: 00297 // USBTRACE("OnInit:"); 00298 // goto Fail; 00299 // 00300 SwAttempt: 00301 #ifdef DEBUG_USB_HOST 00302 USBTRACE("\r\nAccessory mode switch attempt"); 00303 Fail: 00304 #endif 00305 //USBTRACE2("\r\nADK Init Failed, error code: ", rcode); 00306 //NotifyFail(rcode); 00307 Release(); 00308 return rcode; 00309 } 00310 00311 /* Extracts bulk-IN and bulk-OUT endpoint information from config descriptor */ 00312 void ADK::EndpointXtract(uint8_t conf, uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *pep) { 00313 //ErrorMessage<uint8_t>(PSTR("Conf.Val"), conf); 00314 //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface); 00315 //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt); 00316 00317 //added by Yuuichi Akagawa 00318 if(bNumEP == 3) { 00319 return; 00320 } 00321 00322 bConfNum = conf; 00323 00324 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) { 00325 uint8_t index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; 00326 // Fill in the endpoint info structure 00327 epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); 00328 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; 00329 00330 bNumEP++; 00331 00332 //PrintEndpointDescriptor(pep); 00333 } 00334 } 00335 00336 /* Performs a cleanup after failed Init() attempt */ 00337 uint8_t ADK::Release() { 00338 pUsb->GetAddressPool().FreeAddress(bAddress); 00339 00340 bNumEP = 1; //must have to be reset to 1 00341 00342 bAddress = 0; 00343 ready = false; 00344 return 0; 00345 } 00346 00347 uint8_t ADK::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) { 00348 //USBTRACE2("\r\nAddr: ", bAddress ); 00349 //USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr); 00350 return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr); 00351 } 00352 00353 uint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr) { 00354 return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr); 00355 } 00356 00357 void ADK::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) { 00358 Notify(PSTR("Endpoint descriptor:"), 0x80); 00359 Notify(PSTR("\r\nLength:\t\t"), 0x80); 00360 D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80); 00361 Notify(PSTR("\r\nType:\t\t"), 0x80); 00362 D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80); 00363 Notify(PSTR("\r\nAddress:\t"), 0x80); 00364 D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80); 00365 Notify(PSTR("\r\nAttributes:\t"), 0x80); 00366 D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80); 00367 Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); 00368 D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80); 00369 Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); 00370 D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80); 00371 Notify(PSTR("\r\n"), 0x80); 00372 }
Generated on Tue Jul 12 2022 18:12:04 by
1.7.2