]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/USBHost/USBHost3GModule/WANDongleSerialPort.cpp
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / USBHost / USBHost3GModule / WANDongleSerialPort.cpp
1 /* Copyright (c) 2010-2012 mbed.org, MIT License
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
4 * and associated documentation files (the "Software"), to deal in the Software without
5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
7 * Software is furnished to do so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice shall be included in all copies or
10 * substantial portions of the Software.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 */
18
19 #include "USBHostConf.h"
20
21 #ifdef USBHOST_3GMODULE
22
23 #define __DEBUG__ 0
24 #ifndef __MODULE__
25 #define __MODULE__ "WANDongleSerialPort.cpp"
26 #endif
27
28 #include "dbg.h"
29 #include <stdint.h>
30 #include "rtos.h"
31
32 #include "WANDongleSerialPort.h"
33
34 WANDongleSerialPort::WANDongleSerialPort() : cb_tx_en(false), cb_rx_en(false), listener(NULL)
35 {
36   reset();
37 }
38
39 void WANDongleSerialPort::init(USBHost* pHost)
40 {
41   host = pHost;
42 }
43
44 void WANDongleSerialPort::reset()
45 {
46   tx_mtx.lock();
47   rx_mtx.lock();
48
49   bulk_in = NULL;
50   bulk_out = NULL;
51
52   buf_out_len = 0;
53   max_out_size = 0;
54   lock_tx = false;
55   cb_tx_pending = false;
56
57   buf_in_len = 0;
58   buf_in_read_pos = 0;
59   lock_rx = false;
60   cb_rx_pending = false;
61
62   tx_mtx.unlock();
63   rx_mtx.unlock();
64 }
65
66 int WANDongleSerialPort::readPacket()
67 {
68   USB_DBG("Read packet on %p", this);
69   rx_mtx.lock();
70   if(lock_rx)
71   {
72     USB_ERR("Fail");
73     rx_mtx.unlock();
74     return -1;
75   }
76
77   if( bulk_in == NULL )
78   {
79     USB_WARN("Port is disconnected");
80     rx_mtx.unlock();
81     return -1;
82   }
83
84   lock_rx = true; //Receiving
85   rx_mtx.unlock();
86 //  USB_DBG("readPacket");
87   //lock_rx.lock();
88   USB_TYPE res = host->bulkRead(dev, (USBEndpoint *)bulk_in, buf_in, ((USBEndpoint *)bulk_in)->getSize(), false); //Queue transfer
89   if(res != USB_TYPE_PROCESSING)
90   {
91     //lock_rx.unlock();
92     USB_ERR("host->bulkRead() returned %d", res);
93     Thread::wait(100);
94     return -1;
95   }
96   return 0;
97 }
98
99 int WANDongleSerialPort::writePacket()
100 {
101   tx_mtx.lock();
102   if(lock_tx)
103   {
104     USB_ERR("Fail");
105     tx_mtx.unlock();
106     return -1;
107   }
108
109   if( bulk_out == NULL )
110   {
111     USB_WARN("Port is disconnected");
112     tx_mtx.unlock();
113     return -1;
114   }
115
116   lock_tx = true; //Transmitting
117   tx_mtx.unlock();
118 //  USB_DBG("writePacket");
119
120   //lock_tx.lock();
121   USB_TYPE res = host->bulkWrite(dev, (USBEndpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer
122   if(res != USB_TYPE_PROCESSING)
123   {
124     //lock_tx.unlock();
125     USB_ERR("host->bulkWrite() returned %d", res);
126     Thread::wait(100);
127     return -1;
128   }
129   return 0;
130 }
131
132 int WANDongleSerialPort::putc(int c)
133 {
134   tx_mtx.lock();
135   if(!lock_tx)
136   {
137     if(buf_out_len < max_out_size)
138     {
139       buf_out[buf_out_len] = (uint8_t)c;
140       buf_out_len++;
141     }
142   }
143   else
144   {
145     USB_ERR("CAN'T WRITE!");
146   }
147   tx_mtx.unlock();
148   return c;
149 }
150
151 int WANDongleSerialPort::getc()
152 {
153   rx_mtx.lock();
154   int c = 0;
155   if(!lock_rx)
156   {
157     if(buf_in_read_pos < buf_in_len)
158     {
159       c = (int)buf_in[buf_in_read_pos];
160       buf_in_read_pos++;
161     }
162   }
163   else
164   {
165     USB_ERR("CAN'T READ!");
166   }
167   rx_mtx.unlock();
168   return c;
169 }
170
171 int WANDongleSerialPort::readable()
172 {
173   rx_mtx.lock();
174   if (lock_rx)
175   {
176     rx_mtx.unlock();
177     return 0;
178   }
179
180  /* if( !lock_rx.trylock() )
181   {
182     return 0;
183   }*/
184   int res = buf_in_len - buf_in_read_pos;
185   //lock_rx.unlock();
186   rx_mtx.unlock();
187   return res;
188 }
189
190 int WANDongleSerialPort::writeable()
191 {
192   tx_mtx.lock();
193   if (lock_tx)
194   {
195     tx_mtx.unlock();
196     return 0;
197   }
198
199   /*if( !lock_tx.trylock() )
200   {
201     return 0;
202   }*/
203   int res = max_out_size - buf_out_len;
204   tx_mtx.unlock();
205  //lock_tx.unlock();
206   return res;
207 }
208
209 void WANDongleSerialPort::attach(IUSBHostSerialListener* pListener)
210 {
211   if(pListener == NULL)
212   {
213     setupIrq(false, RxIrq);
214     setupIrq(false, TxIrq);
215   }
216   listener = pListener;
217   if(pListener != NULL)
218   {
219     setupIrq(true, RxIrq);
220     setupIrq(true, TxIrq);
221   }
222 }
223
224 void WANDongleSerialPort::setupIrq(bool en, IrqType irq /*= RxIrq*/)
225 {
226   switch(irq)
227   {
228   case RxIrq:
229     rx_mtx.lock();
230     cb_rx_en = en;
231     if(en && cb_rx_pending)
232     {
233       cb_rx_pending = false;
234       rx_mtx.unlock();
235       listener->readable(); //Process the interrupt that was raised
236     }
237     else
238     {
239       rx_mtx.unlock();
240     }
241     break;
242   case TxIrq:
243     tx_mtx.lock();
244     cb_tx_en = en;
245     if(en && cb_tx_pending)
246     {
247       cb_tx_pending = false;
248       tx_mtx.unlock();
249       listener->writeable(); //Process the interrupt that was raised
250     }
251     else
252     {
253       tx_mtx.unlock();
254     }
255     break;
256   }
257 }
258
259
260 void WANDongleSerialPort::connect( USBDeviceConnected* pDev, USBEndpoint* pInEp, USBEndpoint* pOutEp )
261 {
262   dev = pDev;
263   bulk_in = pInEp;
264   bulk_out = pOutEp;
265   max_out_size = bulk_out->getSize();
266   if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
267   {
268     max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
269   }
270   bulk_in->attach(this, &WANDongleSerialPort::rxHandler);
271   bulk_out->attach(this, &WANDongleSerialPort::txHandler);
272   readPacket(); //Start receiving data
273 }
274
275 void WANDongleSerialPort::disconnect( )
276 {
277     reset();
278 }
279
280 //Private methods
281
282
283 void WANDongleSerialPort::rxHandler()
284 {
285   if (((USBEndpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
286   {
287     buf_in_read_pos = 0;
288     buf_in_len = ((USBEndpoint *) bulk_in)->getLengthTransferred(); //Update length
289     //lock_rx.unlock();
290     rx_mtx.lock();
291     lock_rx = false; //Transmission complete
292     if(cb_rx_en)
293     {
294       rx_mtx.unlock();
295       listener->readable(); //Call handler from the IRQ context
296       //readPacket() should be called by the handler subsequently once the buffer has been emptied
297     }
298     else
299     {
300       cb_rx_pending = true; //Queue the callback
301       rx_mtx.unlock();
302     }
303
304   }
305   else //Error, try reading again
306   {
307     //lock_rx.unlock();
308     USB_DBG("Trying again");
309     readPacket();
310   }
311 }
312
313 void WANDongleSerialPort::txHandler()
314 {
315   if (((USBEndpoint *) bulk_out)->getState() == USB_TYPE_IDLE) //Success
316   {
317     tx_mtx.lock();
318     buf_out_len = 0; //Reset length
319     lock_tx = false; //Transmission complete
320     //lock_tx.unlock();
321     if(cb_tx_en)
322     {
323       tx_mtx.unlock();
324       listener->writeable(); //Call handler from the IRQ context
325       //writePacket() should be called by the handler subsequently once the buffer has been filled
326     }
327     else
328     {
329       cb_tx_pending = true; //Queue the callback
330       tx_mtx.unlock();
331     }
332   }
333   else //Error, try reading again
334   {
335     //lock_tx.unlock();
336     writePacket();
337   }
338 }
339
340 #endif /* USBHOST_3GMODULE */