]> git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.cpp
Merge commit '1fe4406f374291ab2e86e95a97341fd9c475fcb8'
[tmk_keyboard.git] / tmk_core / tool / mbed / mbed-sdk / libraries / USBHost / USBHostSerial / USBHostSerial.cpp
1 /* mbed USBHost Library
2 * Copyright (c) 2006-2013 ARM Limited
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 #include "USBHostSerial.h"
18
19 #if USBHOST_SERIAL
20
21 #include "dbg.h"
22
23 #define CHECK_INTERFACE(cls,subcls,proto) \
24 (((cls == 0xFF) && (subcls == 0xFF) && (proto == 0xFF)) /* QUALCOM CDC */ || \
25 ((cls == SERIAL_CLASS) && (subcls == 0x00) && (proto == 0x00)) /* STANDARD CDC */ )
26
27 #if (USBHOST_SERIAL <= 1)
28
29 USBHostSerial::USBHostSerial()
30 {
31 host = USBHost::getHostInst();
32 ports_found = 0;
33 dev_connected = false;
34 }
35
36 bool USBHostSerial::connected()
37 {
38 return dev_connected;
39 }
40
41 void USBHostSerial::disconnect(void)
42 {
43 ports_found = 0;
44 dev = NULL;
45 }
46
47 bool USBHostSerial::connect() {
48
49 if (dev)
50 {
51 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
52 {
53 USBDeviceConnected* d = host->getDevice(i);
54 if (dev == d)
55 return true;
56 }
57 disconnect();
58 }
59 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
60 {
61 USBDeviceConnected* d = host->getDevice(i);
62 if (d != NULL) {
63
64 USB_DBG("Trying to connect serial device \r\n");
65 if(host->enumerate(d, this))
66 break;
67
68 USBEndpoint* bulk_in = d->getEndpoint(port_intf, BULK_ENDPOINT, IN);
69 USBEndpoint* bulk_out = d->getEndpoint(port_intf, BULK_ENDPOINT, OUT);
70 if (bulk_in && bulk_out)
71 {
72 USBHostSerialPort::connect(host,d,port_intf,bulk_in, bulk_out);
73 dev = d;
74 dev_connected = true;
75 }
76 }
77 }
78 return dev != NULL;
79 }
80
81 /*virtual*/ void USBHostSerial::setVidPid(uint16_t vid, uint16_t pid)
82 {
83 // we don't check VID/PID for MSD driver
84 }
85
86 /*virtual*/ bool USBHostSerial::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
87 {
88 if (!ports_found &&
89 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
90 port_intf = intf_nb;
91 ports_found = true;
92 return true;
93 }
94 return false;
95 }
96
97 /*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
98 {
99 if (ports_found && (intf_nb == port_intf)) {
100 if (type == BULK_ENDPOINT)
101 return true;
102 }
103 return false;
104 }
105
106 #else // (USBHOST_SERIAL > 1)
107
108 //------------------------------------------------------------------------------
109
110 USBHostMultiSerial::USBHostMultiSerial()
111 {
112 host = USBHost::getHostInst();
113 dev = NULL;
114 memset(ports, NULL, sizeof(ports));
115 ports_found = 0;
116 dev_connected = false;
117 }
118
119 USBHostMultiSerial::~USBHostMultiSerial()
120 {
121 disconnect();
122 }
123
124 bool USBHostMultiSerial::connected()
125 {
126 return dev_connected;
127 }
128
129 void USBHostMultiSerial::disconnect(void)
130 {
131 for (int port = 0; port < USBHOST_SERIAL; port ++)
132 {
133 if (ports[port])
134 {
135 delete ports[port];
136 ports[port] = NULL;
137 }
138 }
139 ports_found = 0;
140 dev = NULL;
141 }
142
143 bool USBHostMultiSerial::connect() {
144
145 if (dev)
146 {
147 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
148 {
149 USBDeviceConnected* d = host->getDevice(i);
150 if (dev == d)
151 return true;
152 }
153 disconnect();
154 }
155 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
156 {
157 USBDeviceConnected* d = host->getDevice(i);
158 if (d != NULL) {
159
160 USB_DBG("Trying to connect serial device \r\n");
161 if(host->enumerate(d, this))
162 break;
163
164 for (int port = 0; port < ports_found; port ++)
165 {
166 USBEndpoint* bulk_in = d->getEndpoint(port_intf[port], BULK_ENDPOINT, IN);
167 USBEndpoint* bulk_out = d->getEndpoint(port_intf[port], BULK_ENDPOINT, OUT);
168 if (bulk_in && bulk_out)
169 {
170 ports[port] = new USBHostSerialPort();
171 if (ports[port])
172 {
173 ports[port]->connect(host,d,port_intf[port],bulk_in, bulk_out);
174 dev = d;
175 dev_connected = true;
176 }
177 }
178 }
179 }
180 }
181 return dev != NULL;
182 }
183
184 /*virtual*/ void USBHostMultiSerial::setVidPid(uint16_t vid, uint16_t pid)
185 {
186 // we don't check VID/PID for MSD driver
187 }
188
189 /*virtual*/ bool USBHostMultiSerial::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
190 {
191 if ((ports_found < USBHOST_SERIAL) &&
192 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
193 port_intf[ports_found++] = intf_nb;
194 return true;
195 }
196 return false;
197 }
198
199 /*virtual*/ bool USBHostMultiSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
200 {
201 if ((ports_found > 0) && (intf_nb == port_intf[ports_found-1])) {
202 if (type == BULK_ENDPOINT)
203 return true;
204 }
205 return false;
206 }
207
208 #endif
209
210 //------------------------------------------------------------------------------
211
212 #define SET_LINE_CODING 0x20
213
214 USBHostSerialPort::USBHostSerialPort(): circ_buf()
215 {
216 init();
217 }
218
219 void USBHostSerialPort::init(void)
220 {
221 host = NULL;
222 dev = NULL;
223 serial_intf = NULL;
224 size_bulk_in = 0;
225 size_bulk_out = 0;
226 bulk_in = NULL;
227 bulk_out = NULL;
228 line_coding.baudrate = 9600;
229 line_coding.data_bits = 8;
230 line_coding.parity = None;
231 line_coding.stop_bits = 1;
232 circ_buf.flush();
233 }
234
235 void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev,
236 uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out)
237 {
238 host = _host;
239 dev = _dev;
240 serial_intf = _serial_intf;
241 bulk_in = _bulk_in;
242 bulk_out = _bulk_out;
243
244 USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf);
245 dev->setName("Serial", serial_intf);
246 host->registerDriver(dev, serial_intf, this, &USBHostSerialPort::init);
247 baud(9600);
248 size_bulk_in = bulk_in->getSize();
249 size_bulk_out = bulk_out->getSize();
250 bulk_in->attach(this, &USBHostSerialPort::rxHandler);
251 bulk_out->attach(this, &USBHostSerialPort::txHandler);
252 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
253 }
254
255 void USBHostSerialPort::rxHandler() {
256 if (bulk_in) {
257 int len = bulk_in->getLengthTransferred();
258 if (bulk_in->getState() == USB_TYPE_IDLE) {
259 for (int i = 0; i < len; i++) {
260 circ_buf.queue(buf[i]);
261 }
262 rx.call();
263 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
264 }
265 }
266 }
267
268 void USBHostSerialPort::txHandler() {
269 if (bulk_out) {
270 if (bulk_out->getState() == USB_TYPE_IDLE) {
271 tx.call();
272 }
273 }
274 }
275
276 int USBHostSerialPort::_putc(int c) {
277 if (bulk_out) {
278 if (host->bulkWrite(dev, bulk_out, (uint8_t *)&c, 1) == USB_TYPE_OK) {
279 return 1;
280 }
281 }
282 return -1;
283 }
284
285 void USBHostSerialPort::baud(int baudrate) {
286 line_coding.baudrate = baudrate;
287 format(line_coding.data_bits, (Parity)line_coding.parity, line_coding.stop_bits);
288 }
289
290 void USBHostSerialPort::format(int bits, Parity parity, int stop_bits) {
291 line_coding.data_bits = bits;
292 line_coding.parity = parity;
293 line_coding.stop_bits = (stop_bits == 1) ? 0 : 2;
294
295 // set line coding
296 host->controlWrite( dev,
297 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
298 SET_LINE_CODING,
299 0, serial_intf, (uint8_t *)&line_coding, 7);
300 }
301
302 int USBHostSerialPort::_getc() {
303 uint8_t c = 0;
304 if (bulk_in == NULL) {
305 init();
306 return -1;
307 }
308 while (circ_buf.isEmpty());
309 circ_buf.dequeue(&c);
310 return c;
311 }
312
313 int USBHostSerialPort::writeBuf(const char* b, int s)
314 {
315 int c = 0;
316 if (bulk_out)
317 {
318 while (c < s)
319 {
320 int i = (s < size_bulk_out) ? s : size_bulk_out;
321 if (host->bulkWrite(dev, bulk_out, (uint8_t *)(b+c), i) == USB_TYPE_OK)
322 c += i;
323 }
324 }
325 return s;
326 }
327
328 int USBHostSerialPort::readBuf(char* b, int s)
329 {
330 int i = 0;
331 if (bulk_in)
332 {
333 for (i = 0; i < s; )
334 b[i++] = getc();
335 }
336 return i;
337 }
338
339 uint8_t USBHostSerialPort::available() {
340 return circ_buf.available();
341 }
342
343
344
345 #endif
Imprint / Impressum