WANDongleSerialPort.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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. #include "USBHostConf.h"
  19. #ifdef USBHOST_3GMODULE
  20. #define __DEBUG__ 0
  21. #ifndef __MODULE__
  22. #define __MODULE__ "WANDongleSerialPort.cpp"
  23. #endif
  24. #include "dbg.h"
  25. #include <stdint.h>
  26. #include "rtos.h"
  27. #include "WANDongleSerialPort.h"
  28. WANDongleSerialPort::WANDongleSerialPort() : cb_tx_en(false), cb_rx_en(false), listener(NULL)
  29. {
  30. reset();
  31. }
  32. void WANDongleSerialPort::init(USBHost* pHost)
  33. {
  34. host = pHost;
  35. }
  36. void WANDongleSerialPort::reset()
  37. {
  38. tx_mtx.lock();
  39. rx_mtx.lock();
  40. bulk_in = NULL;
  41. bulk_out = NULL;
  42. buf_out_len = 0;
  43. max_out_size = 0;
  44. lock_tx = false;
  45. cb_tx_pending = false;
  46. buf_in_len = 0;
  47. buf_in_read_pos = 0;
  48. lock_rx = false;
  49. cb_rx_pending = false;
  50. tx_mtx.unlock();
  51. rx_mtx.unlock();
  52. }
  53. int WANDongleSerialPort::readPacket()
  54. {
  55. USB_DBG("Read packet on %p", this);
  56. rx_mtx.lock();
  57. if(lock_rx)
  58. {
  59. USB_ERR("Fail");
  60. rx_mtx.unlock();
  61. return -1;
  62. }
  63. if( bulk_in == NULL )
  64. {
  65. USB_WARN("Port is disconnected");
  66. rx_mtx.unlock();
  67. return -1;
  68. }
  69. lock_rx = true; //Receiving
  70. rx_mtx.unlock();
  71. // USB_DBG("readPacket");
  72. //lock_rx.lock();
  73. USB_TYPE res = host->bulkRead(dev, (USBEndpoint *)bulk_in, buf_in, ((USBEndpoint *)bulk_in)->getSize(), false); //Queue transfer
  74. if(res != USB_TYPE_PROCESSING)
  75. {
  76. //lock_rx.unlock();
  77. USB_ERR("host->bulkRead() returned %d", res);
  78. Thread::wait(100);
  79. return -1;
  80. }
  81. return 0;
  82. }
  83. int WANDongleSerialPort::writePacket()
  84. {
  85. tx_mtx.lock();
  86. if(lock_tx)
  87. {
  88. USB_ERR("Fail");
  89. tx_mtx.unlock();
  90. return -1;
  91. }
  92. if( bulk_out == NULL )
  93. {
  94. USB_WARN("Port is disconnected");
  95. tx_mtx.unlock();
  96. return -1;
  97. }
  98. lock_tx = true; //Transmitting
  99. tx_mtx.unlock();
  100. // USB_DBG("writePacket");
  101. //lock_tx.lock();
  102. USB_TYPE res = host->bulkWrite(dev, (USBEndpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer
  103. if(res != USB_TYPE_PROCESSING)
  104. {
  105. //lock_tx.unlock();
  106. USB_ERR("host->bulkWrite() returned %d", res);
  107. Thread::wait(100);
  108. return -1;
  109. }
  110. return 0;
  111. }
  112. int WANDongleSerialPort::putc(int c)
  113. {
  114. tx_mtx.lock();
  115. if(!lock_tx)
  116. {
  117. if(buf_out_len < max_out_size)
  118. {
  119. buf_out[buf_out_len] = (uint8_t)c;
  120. buf_out_len++;
  121. }
  122. }
  123. else
  124. {
  125. USB_ERR("CAN'T WRITE!");
  126. }
  127. tx_mtx.unlock();
  128. return c;
  129. }
  130. int WANDongleSerialPort::getc()
  131. {
  132. rx_mtx.lock();
  133. int c = 0;
  134. if(!lock_rx)
  135. {
  136. if(buf_in_read_pos < buf_in_len)
  137. {
  138. c = (int)buf_in[buf_in_read_pos];
  139. buf_in_read_pos++;
  140. }
  141. }
  142. else
  143. {
  144. USB_ERR("CAN'T READ!");
  145. }
  146. rx_mtx.unlock();
  147. return c;
  148. }
  149. int WANDongleSerialPort::readable()
  150. {
  151. rx_mtx.lock();
  152. if (lock_rx)
  153. {
  154. rx_mtx.unlock();
  155. return 0;
  156. }
  157. /* if( !lock_rx.trylock() )
  158. {
  159. return 0;
  160. }*/
  161. int res = buf_in_len - buf_in_read_pos;
  162. //lock_rx.unlock();
  163. rx_mtx.unlock();
  164. return res;
  165. }
  166. int WANDongleSerialPort::writeable()
  167. {
  168. tx_mtx.lock();
  169. if (lock_tx)
  170. {
  171. tx_mtx.unlock();
  172. return 0;
  173. }
  174. /*if( !lock_tx.trylock() )
  175. {
  176. return 0;
  177. }*/
  178. int res = max_out_size - buf_out_len;
  179. tx_mtx.unlock();
  180. //lock_tx.unlock();
  181. return res;
  182. }
  183. void WANDongleSerialPort::attach(IUSBHostSerialListener* pListener)
  184. {
  185. if(pListener == NULL)
  186. {
  187. setupIrq(false, RxIrq);
  188. setupIrq(false, TxIrq);
  189. }
  190. listener = pListener;
  191. if(pListener != NULL)
  192. {
  193. setupIrq(true, RxIrq);
  194. setupIrq(true, TxIrq);
  195. }
  196. }
  197. void WANDongleSerialPort::setupIrq(bool en, IrqType irq /*= RxIrq*/)
  198. {
  199. switch(irq)
  200. {
  201. case RxIrq:
  202. rx_mtx.lock();
  203. cb_rx_en = en;
  204. if(en && cb_rx_pending)
  205. {
  206. cb_rx_pending = false;
  207. rx_mtx.unlock();
  208. listener->readable(); //Process the interrupt that was raised
  209. }
  210. else
  211. {
  212. rx_mtx.unlock();
  213. }
  214. break;
  215. case TxIrq:
  216. tx_mtx.lock();
  217. cb_tx_en = en;
  218. if(en && cb_tx_pending)
  219. {
  220. cb_tx_pending = false;
  221. tx_mtx.unlock();
  222. listener->writeable(); //Process the interrupt that was raised
  223. }
  224. else
  225. {
  226. tx_mtx.unlock();
  227. }
  228. break;
  229. }
  230. }
  231. void WANDongleSerialPort::connect( USBDeviceConnected* pDev, USBEndpoint* pInEp, USBEndpoint* pOutEp )
  232. {
  233. dev = pDev;
  234. bulk_in = pInEp;
  235. bulk_out = pOutEp;
  236. max_out_size = bulk_out->getSize();
  237. if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
  238. {
  239. max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
  240. }
  241. bulk_in->attach(this, &WANDongleSerialPort::rxHandler);
  242. bulk_out->attach(this, &WANDongleSerialPort::txHandler);
  243. readPacket(); //Start receiving data
  244. }
  245. void WANDongleSerialPort::disconnect( )
  246. {
  247. reset();
  248. }
  249. //Private methods
  250. void WANDongleSerialPort::rxHandler()
  251. {
  252. if (((USBEndpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
  253. {
  254. buf_in_read_pos = 0;
  255. buf_in_len = ((USBEndpoint *) bulk_in)->getLengthTransferred(); //Update length
  256. //lock_rx.unlock();
  257. rx_mtx.lock();
  258. lock_rx = false; //Transmission complete
  259. if(cb_rx_en)
  260. {
  261. rx_mtx.unlock();
  262. listener->readable(); //Call handler from the IRQ context
  263. //readPacket() should be called by the handler subsequently once the buffer has been emptied
  264. }
  265. else
  266. {
  267. cb_rx_pending = true; //Queue the callback
  268. rx_mtx.unlock();
  269. }
  270. }
  271. else //Error, try reading again
  272. {
  273. //lock_rx.unlock();
  274. USB_DBG("Trying again");
  275. readPacket();
  276. }
  277. }
  278. void WANDongleSerialPort::txHandler()
  279. {
  280. if (((USBEndpoint *) bulk_out)->getState() == USB_TYPE_IDLE) //Success
  281. {
  282. tx_mtx.lock();
  283. buf_out_len = 0; //Reset length
  284. lock_tx = false; //Transmission complete
  285. //lock_tx.unlock();
  286. if(cb_tx_en)
  287. {
  288. tx_mtx.unlock();
  289. listener->writeable(); //Call handler from the IRQ context
  290. //writePacket() should be called by the handler subsequently once the buffer has been filled
  291. }
  292. else
  293. {
  294. cb_tx_pending = true; //Queue the callback
  295. tx_mtx.unlock();
  296. }
  297. }
  298. else //Error, try reading again
  299. {
  300. //lock_tx.unlock();
  301. writePacket();
  302. }
  303. }
  304. #endif /* USBHOST_3GMODULE */