source: rtos_arduino/trunk/arduino_lib/libraries/USBHost/src/adk.cpp

Last change on this file was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 10.0 KB
Line 
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 uint32_t ADK::epDataInIndex = 1;
23const uint32_t ADK::epDataOutIndex = 2;
24
25/**
26 * \brief ADK class constructor.
27 */
28ADK::ADK(USBHost *p, const char* pmanufacturer,
29 const char* pmodel,
30 const char* pdescription,
31 const char* pversion,
32 const char* puri,
33 const char* pserial) :
34 manufacturer(pmanufacturer),
35 model(pmodel),
36 description(pdescription),
37 version(pversion),
38 uri(puri),
39 serial(pserial),
40 pUsb(p),
41 bAddress(0),
42 bNumEP(1),
43 ready(false)
44{
45 // Initialize endpoint data structures
46 for (uint32_t i = 0; i < ADK_MAX_ENDPOINTS; ++i)
47 {
48 epInfo[i].deviceEpNum = 0;
49 epInfo[i].hostPipeNum = 0;
50 epInfo[i].maxPktSize = (i) ? 0 : 8;
51 epInfo[i].epAttribs = 0;
52 epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
53 }
54
55 // Register in USB subsystem
56 if (pUsb)
57 {
58 pUsb->RegisterDeviceClass(this);
59 }
60}
61
62/**
63 * \brief Initialize connection to an Android Phone.
64 *
65 * \param parent USB device address of the Parent device.
66 * \param port USB device base address.
67 * \param lowspeed USB device speed.
68 *
69 * \return 0 on success, error code otherwise.
70 */
71uint32_t ADK::Init(uint32_t parent, uint32_t port, uint32_t lowspeed)
72{
73
74 uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)];
75 uint32_t rcode = 0;
76 UsbDevice *p = NULL;
77 EpInfo *oldep_ptr = NULL;
78 uint32_t adkproto = -1;
79 uint32_t num_of_conf = 0;
80
81 // Get memory address of USB device address pool
82 AddressPool &addrPool = pUsb->GetAddressPool();
83
84 TRACE_USBHOST(printf("ADK::Init\r\n");)
85
86 // Check if address has already been assigned to an instance
87 if (bAddress)
88 {
89 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
90 }
91
92 // Get pointer to pseudo device with address 0 assigned
93 p = addrPool.GetUsbDevicePtr(0);
94
95 if (!p)
96 {
97 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
98 }
99
100 if (!p->epinfo)
101 {
102 return USB_ERROR_EPINFO_IS_NULL;
103 }
104
105 // Save old pointer to EP_RECORD of address 0
106 oldep_ptr = p->epinfo;
107
108 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
109 p->epinfo = epInfo;
110
111 p->lowspeed = lowspeed;
112
113 // Get device descriptor
114 rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
115
116 // Restore p->epinfo
117 p->epinfo = oldep_ptr;
118
119 if (rcode)
120 {
121 goto FailGetDevDescr;
122 }
123
124 // Allocate new address according to device class
125 bAddress = addrPool.AllocAddress(parent, false, port);
126
127 // Extract Max Packet Size from device descriptor
128 epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
129
130 // Assign new address to the device
131 rcode = pUsb->setAddr(0, 0, bAddress);
132 if (rcode)
133 {
134 p->lowspeed = false;
135 addrPool.FreeAddress(bAddress);
136 bAddress = 0;
137 TRACE_USBHOST(printf("ADK::Init : setAddr failed with rcode %lu\r\n", rcode);)
138 return rcode;
139 }
140
141 TRACE_USBHOST(printf("ADK::Init : device address is now %lu\r\n", bAddress);)
142
143 p->lowspeed = false;
144
145 //get pointer to assigned address record
146 p = addrPool.GetUsbDevicePtr(bAddress);
147 if (!p)
148 {
149 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
150 }
151
152 p->lowspeed = lowspeed;
153
154 // Assign epInfo to epinfo pointer - only EP0 is known
155 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
156 if (rcode)
157 {
158 goto FailSetDevTblEntry;
159 }
160
161 // Check if ADK device is already in accessory mode; if yes, configure and exit
162 if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor == ADK_VID &&
163 (((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADB_PID))
164 {
165 TRACE_USBHOST(printf("ADK::Init : Accessory mode device detected\r\n");)
166
167 /* Go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
168 num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
169
170 TRACE_USBHOST(printf("ADK::Init : number of configuration is %lu\r\n", num_of_conf);)
171
172 for (uint32_t i = 0; i < num_of_conf; ++i)
173 {
174 ConfigDescParser<0, 0, 0, 0> confDescrParser(this);
175
176 delay(1);
177 rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
178
179#if defined(XOOM)
180 //Added by Jaylen Scott Vanorden
181 if (rcode)
182 {
183 TRACE_USBHOST(printf("ADK::Init : Got 1st bad code for config: %lu\r\n", rcode);)
184
185 // Try once more
186 rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
187 }
188#endif
189
190 if (rcode)
191 {
192 goto FailGetConfDescr;
193 }
194
195 if (bNumEP > 2)
196 {
197 break;
198 }
199 }
200
201 if (bNumEP == 3)
202 {
203 // Assign epInfo to epinfo pointer - this time all 3 endpoins
204 rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
205 if (rcode)
206 {
207 goto FailSetDevTblEntry;
208 }
209 }
210
211 // Set Configuration Value
212 rcode = pUsb->setConf(bAddress, 0, bConfNum);
213 if (rcode)
214 {
215 goto FailSetConf;
216 }
217
218 TRACE_USBHOST(printf("ADK::Init : ADK device configured successfully\r\n");)
219 ready = true;
220
221 return 0;
222 }
223
224 // Probe device - get accessory protocol revision
225 delay(1);
226 rcode = getProto((uint8_t*)&adkproto);
227
228#if defined(XOOM)
229 // Added by Jaylen Scott Vanorden
230 if (rcode)
231 {
232 TRACE_USBHOST(printf("ADK::Init : Got 1st bad code for config: %lu\r\n", rcode);)
233
234 // Try once more
235 rcode = getProto((uint8_t*)&adkproto );
236 }
237#endif
238
239 if (rcode)
240 {
241 goto FailGetProto;
242 }
243 TRACE_USBHOST(printf("ADK::Init : DK protocol rev. %lu", adkproto);)
244
245 // Send ID strings
246 sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer);
247 sendStr(ACCESSORY_STRING_MODEL, model);
248 sendStr(ACCESSORY_STRING_DESCRIPTION, description);
249 sendStr(ACCESSORY_STRING_VERSION, version);
250 sendStr(ACCESSORY_STRING_URI, uri);
251 sendStr(ACCESSORY_STRING_SERIAL, serial);
252
253 // Switch to accessory mode
254 // The Android phone will reset
255 rcode = switchAcc();
256 if (rcode)
257 {
258 goto FailSwAcc;
259 }
260 rcode = -1;
261 goto SwAttempt; // Switch to accessory mode
262
263 // Diagnostic messages
264FailGetDevDescr:
265 TRACE_USBHOST(printf("ADK::Init getDevDescr : ");)
266 goto Fail;
267
268FailSetDevTblEntry:
269 TRACE_USBHOST(printf("ADK::Init setDevTblEn : ");)
270 goto Fail;
271
272FailGetProto:
273 TRACE_USBHOST(printf("ADK::Init getProto : ");)
274 goto Fail;
275
276FailSwAcc:
277 TRACE_USBHOST(printf("ADK::Init swAcc : ");)
278 goto Fail;
279
280SwAttempt:
281 TRACE_USBHOST(printf("ADK::Init Accessory mode switch attempt : ");)
282 goto Fail;
283
284FailGetConfDescr:
285 TRACE_USBHOST(printf("ADK::Init getConf : ");)
286 goto Fail;
287
288FailSetConf:
289 TRACE_USBHOST(printf("ADK::Init setConf : ");)
290 goto Fail;
291
292Fail:
293 TRACE_USBHOST(printf("error code: %lu\r\n", rcode);)
294 Release();
295 return rcode;
296}
297
298/**
299 * \brief Extract bulk-IN and bulk-OUT endpoint information from configuration
300 * descriptor.
301 *
302 * \param conf Configuration number.
303 * \param iface Interface number.
304 * \param alt Alternate setting.
305 * \param proto Protocol version used.
306 * \param pep Pointer to endpoint descriptor.
307 */
308void ADK::EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
309{
310 if (bNumEP == 3)
311 {
312 return;
313 }
314
315 bConfNum = conf;
316
317 uint32_t index = 0;
318 uint32_t pipe = 0;
319
320 if ((pep->bmAttributes & 0x02) == 2)
321 {
322 index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
323 }
324
325 // Fill in the endpoint info structure
326 epInfo[index].deviceEpNum = pep->bEndpointAddress & 0x0F;
327 epInfo[index].maxPktSize = pep->wMaxPacketSize;
328
329 TRACE_USBHOST(printf("ADK::EndpointXtract : Found new endpoint\r\n");)
330 TRACE_USBHOST(printf("ADK::EndpointXtract : deviceEpNum: %lu\r\n", epInfo[index].deviceEpNum);)
331 TRACE_USBHOST(printf("ADK::EndpointXtract : maxPktSize: %lu\r\n", epInfo[index].maxPktSize);)
332 TRACE_USBHOST(printf("ADK::EndpointXtract : index: %lu\r\n", index);)
333
334 if (index == epDataInIndex)
335 pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
336 else if (index == epDataOutIndex)
337 pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_OUT, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
338
339 // Ensure pipe allocation is okay
340 if (pipe == 0)
341 {
342 TRACE_USBHOST(printf("ADK::EndpointXtract : Pipe allocation failure\r\n");)
343 // Enumeration failed, so user should not perform write/read since isConnected will return false
344 return;
345 }
346
347 epInfo[index].hostPipeNum = pipe;
348
349 bNumEP++;
350}
351
352/**
353 * \brief Release USB allocated resources (pipes and address).
354 *
355 * \note Release call is made from USBHost.task() on disconnection events.
356 * \note Release call is made from Init() on enumeration failure.
357 *
358 * \return Always 0.
359 */
360uint32_t ADK::Release()
361{
362 // Free allocated host pipes
363 UHD_Pipe_Free(epInfo[epDataInIndex].hostPipeNum);
364 UHD_Pipe_Free(epInfo[epDataOutIndex].hostPipeNum);
365
366 // Free allocated USB address
367 pUsb->GetAddressPool().FreeAddress(bAddress);
368
369 // Must have to be reset to 1
370 bNumEP = 1;
371
372 bAddress = 0;
373 ready = false;
374
375 return 0;
376}
377
378/**
379 * \brief Read from ADK.
380 *
381 * \param nreadbytes Return value containing the number of read bytes.
382 * \param datalen Buffer length.
383 * \param dataptr Buffer to store the incoming data.
384 *
385 * \return 0 on success, error code otherwise.
386 */
387uint32_t ADK::read(uint32_t *nreadbytes, uint32_t datalen, uint8_t *dataptr)
388{
389 *nreadbytes = datalen;
390 return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].deviceEpNum, nreadbytes, dataptr);
391}
392
393/**
394 * \brief Write to ADK.
395 *
396 * \param datalen Amount of data to send. This parameter shall not exceed
397 * dataptr length.
398 * \param dataptr Buffer containing the data to be sent.
399 *
400 * \return 0 on success, error code otherwise.
401 */
402uint32_t ADK::write(uint32_t datalen, uint8_t *dataptr)
403{
404 return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].deviceEpNum, datalen, dataptr);
405}
Note: See TracBrowser for help on using the repository browser.