USB Host Shield 2.0
Loading...
Searching...
No Matches
adk.cpp
Go to the documentation of this file.
1/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2
3This software may be distributed and modified under the terms of the GNU
4General Public License version 2 (GPL2) as published by the Free Software
5Foundation and appearing in the file GPL2.TXT included in the packaging of
6this file. Please note that GPL2 Section 2[b] requires that all works based
7on this software must also be made publicly available under the terms of
8the GPL2 ("Copyleft").
9
10Contact information
11-------------------
12
13Circuits At Home, LTD
14Web : http://www.circuitsathome.com
15e-mail : support@circuitsathome.com
16 */
17
18/* Google ADK interface */
19
20#include "adk.h"
21
22const uint8_t ADK::epDataInIndex = 1;
23const uint8_t ADK::epDataOutIndex = 2;
24
25ADK::ADK(USB *p, const char* manufacturer,
26 const char* model,
27 const char* description,
28 const char* version,
29 const char* uri,
30 const char* serial) :
31
32/* ADK ID Strings */
33manufacturer(manufacturer),
34model(model),
35description(description),
36version(version),
37uri(uri),
38serial(serial),
39pUsb(p), //pointer to USB class instance - mandatory
40bAddress(0), //device address - mandatory
41bConfNum(0), //configuration number
42bNumEP(1), //if config descriptor needs to be parsed
43ready(false) {
44 // initialize endpoint data structures
45 for(uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) {
46 epInfo[i].epAddr = 0;
47 epInfo[i].maxPktSize = (i) ? 0 : 8;
48 epInfo[i].bmSndToggle = 0;
49 epInfo[i].bmRcvToggle = 0;
51 }//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++...
52
53 // register in USB subsystem
54 if(pUsb) {
55 pUsb->RegisterDeviceClass(this); //set devConfig[] entry
56 }
57}
58
59uint8_t ADK::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
60 return Init(parent, port, lowspeed); // Just call Init. Yes, really!
61}
62
63/* Connection initialization of an Android phone */
64uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
65 uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
66 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
67 uint8_t rcode;
68 uint8_t num_of_conf; // number of configurations
69 UsbDevice *p = NULL;
70 EpInfo *oldep_ptr = NULL;
71
72 // get memory address of USB device address pool
73 AddressPool &addrPool = pUsb->GetAddressPool();
74
75 USBTRACE("\r\nADK Init");
76
77 // check if address has already been assigned to an instance
78 if(bAddress) {
79 USBTRACE("\r\nAddress in use");
81 }
82
83 // Get pointer to pseudo device with address 0 assigned
84 p = addrPool.GetUsbDevicePtr(0);
85
86 if(!p) {
87 USBTRACE("\r\nAddress not found");
89 }
90
91 if(!p->epinfo) {
92 USBTRACE("epinfo is null\r\n");
94 }
95
96 // Save old pointer to EP_RECORD of address 0
97 oldep_ptr = p->epinfo;
98
99 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
100 p->epinfo = epInfo;
101
102 p->lowspeed = lowspeed;
103
104 // Get device descriptor
105 rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
106
107 // Restore p->epinfo
108 p->epinfo = oldep_ptr;
109
110 if(rcode) {
111 goto FailGetDevDescr;
112 }
113
114 // Allocate new address according to device class
115 bAddress = addrPool.AllocAddress(parent, false, port);
116
117 // Extract Max Packet Size from device descriptor
118 epInfo[0].maxPktSize = udd->bMaxPacketSize0;
119
120 // Assign new address to the device
121 rcode = pUsb->setAddr(0, 0, bAddress);
122 if(rcode) {
123 p->lowspeed = false;
124 addrPool.FreeAddress(bAddress);
125 bAddress = 0;
126 //USBTRACE2("setAddr:",rcode);
127 return rcode;
128 }//if (rcode...
129
130 //USBTRACE2("\r\nAddr:", bAddress);
131 // Spec says you should wait at least 200ms.
132 //delay(300);
133
134 p->lowspeed = false;
135
136 //get pointer to assigned address record
137 p = addrPool.GetUsbDevicePtr(bAddress);
138 if(!p) {
140 }
141
142 p->lowspeed = lowspeed;
143
144 // Assign epInfo to epinfo pointer - only EP0 is known
145 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
146 if(rcode) {
147 goto FailSetDevTblEntry;
148 }
149
150 //check if ADK device is already in accessory mode; if yes, configure and exit
151 if(udd->idVendor == ADK_VID &&
152 (udd->idProduct == ADK_PID || udd->idProduct == ADB_PID)) {
153 USBTRACE("\r\nAcc.mode device detected");
154 /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
155 num_of_conf = udd->bNumConfigurations;
156
157 //USBTRACE2("\r\nNC:",num_of_conf);
158 for(uint8_t i = 0; i < num_of_conf; i++) {
159 ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this);
160 delay(1);
162#if defined(XOOM)
163 //added by Jaylen Scott Vanorden
164 if(rcode) {
165 USBTRACE2("\r\nGot 1st bad code for config: ", rcode);
166 // Try once more
168 }
169#endif
170 if(rcode) {
171 goto FailGetConfDescr;
172 }
173 if(bNumEP > 2) {
174 break;
175 }
176 } // for (uint8_t i=0; i<num_of_conf; i++...
177
178 if(bNumEP == 3) {
179 // Assign epInfo to epinfo pointer - this time all 3 endpoins
181 if(rcode) {
183 }
184 }
185
186 // Set Configuration Value
188 if(rcode) {
189 goto FailSetConfDescr;
190 }
191 /* print endpoint structure */
192 /*
193 USBTRACE("\r\nEndpoint Structure:");
194 USBTRACE("\r\nEP0:");
195 USBTRACE2("\r\nAddr: ", epInfo[0].epAddr);
196 USBTRACE2("\r\nMax.pkt.size: ", epInfo[0].maxPktSize);
197 USBTRACE2("\r\nAttr: ", epInfo[0].epAttribs);
198 USBTRACE("\r\nEpout:");
199 USBTRACE2("\r\nAddr: ", epInfo[epDataOutIndex].epAddr);
200 USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataOutIndex].maxPktSize);
201 USBTRACE2("\r\nAttr: ", epInfo[epDataOutIndex].epAttribs);
202 USBTRACE("\r\nEpin:");
203 USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr);
204 USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize);
205 USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs);
206 */
207
208 USBTRACE("\r\nConfiguration successful");
209 ready = true;
210 return 0; //successful configuration
211 }//if( buf->idVendor == ADK_VID...
212
213 //probe device - get accessory protocol revision
214 {
215 uint16_t adkproto = -1;
216 delay(1);
217 rcode = getProto((uint8_t*) & adkproto);
218#if defined(XOOM)
219 //added by Jaylen Scott Vanorden
220 if(rcode) {
221 USBTRACE2("\r\nGot 1st bad code for proto: ", rcode);
222 // Try once more
223 rcode = getProto((uint8_t*) & adkproto);
224 }
225#endif
226 if(rcode) {
227 goto FailGetProto; //init fails
228 }
229 USBTRACE2("\r\nADK protocol rev. ", adkproto);
230 }
231
232 delay(100);
233
234 //sending ID strings
235 sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer);
236 delay(10);
237 sendStr(ACCESSORY_STRING_MODEL, model);
238 delay(10);
239 sendStr(ACCESSORY_STRING_DESCRIPTION, description);
240 delay(10);
241 sendStr(ACCESSORY_STRING_VERSION, version);
242 delay(10);
243 sendStr(ACCESSORY_STRING_URI, uri);
244 delay(10);
245 sendStr(ACCESSORY_STRING_SERIAL, serial);
246
247 delay(100);
248
249 //switch to accessory mode
250 //the Android phone will reset
251 rcode = switchAcc();
252 if(rcode) {
253 goto FailSwAcc; //init fails
254 }
256 delay(100); // Give Android a chance to do its reset. This is a guess, and possibly could be lower.
257 goto SwAttempt; //switch to accessory mode attempted
258
259 /* diagnostic messages */
261#ifdef DEBUG_USB_HOST
263 goto Fail;
264#endif
265
267#ifdef DEBUG_USB_HOST
269 goto Fail;
270#endif
271
273#ifdef DEBUG_USB_HOST
275 goto Fail;
276#endif
277
279#ifdef DEBUG_USB_HOST
281 goto Fail;
282#endif
283
285#ifdef DEBUG_USB_HOST
286 USBTRACE("\r\ngetProto:");
287 goto Fail;
288#endif
289
291#ifdef DEBUG_USB_HOST
292 USBTRACE("\r\nswAcc:");
293 goto Fail;
294#endif
295
296 //FailOnInit:
297 // USBTRACE("OnInit:");
298 // goto Fail;
299 //
301#ifdef DEBUG_USB_HOST
302 USBTRACE("\r\nAccessory mode switch attempt");
303Fail:
304#endif
305 //USBTRACE2("\r\nADK Init Failed, error code: ", rcode);
306 //NotifyFail(rcode);
307 Release();
308 return rcode;
309}
310
311/* Extracts bulk-IN and bulk-OUT endpoint information from config descriptor */
313 //ErrorMessage<uint8_t>(PSTR("Conf.Val"), conf);
314 //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
315 //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
316
317 //added by Yuuichi Akagawa
318 if(bNumEP == 3) {
319 return;
320 }
321
322 bConfNum = conf;
323
324 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) {
325 uint8_t index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
326 // Fill in the endpoint info structure
327 epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
328 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
329
330 bNumEP++;
331
332 //PrintEndpointDescriptor(pep);
333 }
334}
335
336/* Performs a cleanup after failed Init() attempt */
339
340 bNumEP = 1; //must have to be reset to 1
341
342 bAddress = 0;
343 ready = false;
344 return 0;
345}
346
348 //USBTRACE2("\r\nAddr: ", bAddress );
349 //USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr);
351}
352
356
358 Notify(PSTR("Endpoint descriptor:"), 0x80);
359 Notify(PSTR("\r\nLength:\t\t"), 0x80);
360 D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
361 Notify(PSTR("\r\nType:\t\t"), 0x80);
362 D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
363 Notify(PSTR("\r\nAddress:\t"), 0x80);
364 D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
365 Notify(PSTR("\r\nAttributes:\t"), 0x80);
366 D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
367 Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
368 D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
369 Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
370 D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
371 Notify(PSTR("\r\n"), 0x80);
372}
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition UsbCore.h:108
#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET
Definition UsbCore.h:111
#define USB_ERROR_EPINFO_IS_NULL
Definition UsbCore.h:106
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition UsbCore.h:105
#define USB_NAK_MAX_POWER
Definition address.h:34
#define USB_NAK_NOWAIT
Definition address.h:36
#define ACCESSORY_STRING_URI
Definition adk.h:46
#define ACCESSORY_STRING_MANUFACTURER
Definition adk.h:42
#define ACCESSORY_STRING_SERIAL
Definition adk.h:47
#define ADK_PID
Definition adk.h:26
#define ADB_PID
Definition adk.h:27
#define ADK_VID
Definition adk.h:25
#define ACCESSORY_STRING_MODEL
Definition adk.h:43
#define ACCESSORY_STRING_DESCRIPTION
Definition adk.h:44
#define ACCESSORY_STRING_VERSION
Definition adk.h:45
#define ADK_MAX_ENDPOINTS
Definition adk.h:49
bool ready
Definition adk.h:78
uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed)
Definition adk.cpp:59
ADK(USB *pUsb, const char *manufacturer, const char *model, const char *description, const char *version, const char *uri, const char *serial)
Definition adk.cpp:25
uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr)
Definition adk.cpp:347
EpInfo epInfo[ADK_MAX_ENDPOINTS]
Definition adk.h:81
uint8_t Release()
Definition adk.cpp:337
uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition adk.cpp:64
static const uint8_t epDataInIndex
Definition adk.h:69
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition adk.cpp:312
uint8_t bAddress
Definition adk.h:74
USB * pUsb
Definition adk.h:73
uint8_t SndData(uint16_t nbytes, uint8_t *dataptr)
Definition adk.cpp:353
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)
Definition adk.cpp:357
static const uint8_t epDataOutIndex
Definition adk.h:70
uint8_t bNumEP
Definition adk.h:77
uint8_t bConfNum
Definition adk.h:75
virtual void FreeAddress(uint8_t addr)=0
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
Definition UsbCore.h:220
AddressPool & GetAddressPool()
Definition UsbCore.h:236
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition Usb.cpp:801
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition Usb.cpp:850
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition Usb.cpp:841
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition UsbCore.h:240
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition Usb.cpp:806
uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
Definition Usb.cpp:64
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval=0)
Definition Usb.cpp:209
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data)
Definition Usb.cpp:303
#define USBTRACE2(s, r)
Definition macros.h:84
#define USBTRACE(s)
Definition macros.h:82
#define NotifyFailSetConfDescr(...)
Definition message.h:60
#define Notify(...)
Definition message.h:51
#define NotifyFailGetConfDescr(...)
Definition message.h:56
#define NotifyFailSetDevTblEntry(...)
Definition message.h:55
#define NotifyFailGetDevDescr(...)
Definition message.h:54
uint8_t bmNakPower
Definition address.h:49
uint8_t bmRcvToggle
Definition address.h:48
uint8_t epAddr
Definition address.h:40
uint8_t maxPktSize
Definition address.h:41
uint8_t bmSndToggle
Definition address.h:47
EpInfo * epinfo
Definition address.h:83
bool lowspeed
Definition address.h:86
#define USB_TRANSFER_TYPE_BULK
Definition usb_ch9.h:92
#define bmUSB_TRANSFER_TYPE
Definition usb_ch9.h:94
#define PSTR(str)