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
AndroidAccessory(const char * manufacturer,const char * model,const char * description,const char * version,const char * uri,const char * serial)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
powerOn(void)54 void AndroidAccessory::powerOn(void)
55 {
56 max.powerOn();
57 delay(200);
58 }
59
getProtocol(byte addr)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
sendString(byte addr,int index,const char * str)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
switchDevice(byte addr)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
findEndpoints(byte addr,EP_RECORD * inEp,EP_RECORD * outEp)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
configureAndroid(void)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
isConnected(void)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
read(void * buff,int len,unsigned int nakLimit)263 int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit)
264 {
265 return usb.newInTransfer(1, in, len, (char *)buff, nakLimit);
266 }
267
write(void * buff,int len)268 int AndroidAccessory::write(void *buff, int len)
269 {
270 usb.outTransfer(1, out, len, (char *)buff);
271 return len;
272 }
273
274