]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/USBHost/USBHostSerial/USBHostSerial.cpp
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / 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