PHS module SMA-01 library. see: https://developer.mbed.org/users/phsfan/notebook/abitusbmodem/

Dependencies:   Socket lwip-sys lwip

Dependents:   AbitUSBModem_HTTPTest AbitUSBModem_MQTTTest AbitUSBModem_WebsocketTest AbitUSBModem_SMSTest

Fork of VodafoneUSBModem by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHostPhs.cpp Source File

USBHostPhs.cpp

00001 /* USBHostPhs.cpp */
00002 /* Modified by 2015 phsfan
00003  *  for ABIT SMA-01
00004  */
00005 /* mbed USBHost Library
00006  * Copyright (c) 2006-2013 ARM Limited
00007  *
00008  * Licensed under the Apache License, Version 2.0 (the "License");
00009  * you may not use this file except in compliance with the License.
00010  * You may obtain a copy of the License at
00011  *
00012  *     http://www.apache.org/licenses/LICENSE-2.0
00013  *
00014  * Unless required by applicable law or agreed to in writing, software
00015  * distributed under the License is distributed on an "AS IS" BASIS,
00016  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00017  * See the License for the specific language governing permissions and
00018  * limitations under the License.
00019  */
00020 
00021 /* WANDongle.cpp, WANDongleSerialPort.cpp */
00022 /* Copyright (c) 2010-2012 mbed.org, MIT License
00023 *
00024 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00025 * and associated documentation files (the "Software"), to deal in the Software without
00026 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00027 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00028 * Software is furnished to do so, subject to the following conditions:
00029 *
00030 * The above copyright notice and this permission notice shall be included in all copies or
00031 * substantial portions of the Software.
00032 *
00033 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00034 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00035 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00036 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00037 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00038 */
00039 
00040 
00041 #define __DEBUG__ 0
00042 #ifndef __MODULE__
00043 #define __MODULE__ "USBHostPhs.cpp"
00044 #endif
00045 
00046 #include "core/dbg.h"
00047 #include <cstdint>
00048 #include "rtos.h"
00049 
00050 #include "USBHostPhs.h"
00051 
00052 #define CHECK_INTERFACE(cls,subcls,proto) \
00053         (((cls == 0xFF)         && (subcls == 0xFF) && (proto == 0xFF)) /* QUALCOM CDC */  || \
00054          ((cls == SERIAL_CLASS) && (subcls == 0x00) && (proto == 0x00)) /* STANDARD CDC */ )
00055 
00056 USBHostPhs::USBHostPhs()
00057 {
00058     host = USBHost::getHostInst();
00059     ports_found = 0;
00060     dev_connected = false;
00061 }
00062 
00063 bool USBHostPhs::connected()
00064 {
00065     return dev_connected;
00066 }
00067 
00068 void USBHostPhs::disconnect(void)
00069 {
00070     USBHostPhsPort::reset();
00071     ports_found = 0;
00072     dev = NULL;
00073 }
00074 
00075 bool USBHostPhs::connect() {
00076 
00077     if (dev)
00078     {
00079         for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
00080         {
00081             USBDeviceConnected* d = host->getDevice(i);
00082             if (dev == d)
00083                 return true;
00084         }
00085         disconnect();
00086     }
00087     for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
00088     {
00089         USBDeviceConnected* d = host->getDevice(i);
00090         if (d != NULL) {
00091 
00092             USB_DBG("Trying to connect serial device \r\n");
00093             if(host->enumerate(d, this))
00094                 break;
00095             DBG("Device has VID:%04x PID:%04x", d->getVid(), d->getPid());
00096             if ((d->getVid() != PHS_VID) || (d->getPid() != PHS_PID)) break;
00097 
00098             USBEndpoint* bulk_in  = d->getEndpoint(port_intf, BULK_ENDPOINT, IN);
00099             USBEndpoint* bulk_out = d->getEndpoint(port_intf, BULK_ENDPOINT, OUT);
00100             if (bulk_in && bulk_out)
00101             {
00102                 USBHostPhsPort::connect(host,d,port_intf,bulk_in, bulk_out);
00103                 dev = d;
00104                 dev_connected = true;
00105                 DBG("Device connected");
00106             }
00107         }
00108     }
00109     return dev != NULL;
00110 }
00111 
00112 /*virtual*/ void USBHostPhs::setVidPid(uint16_t vid, uint16_t pid)
00113 {
00114     // we don't check VID/PID for MSD driver
00115 }
00116 
00117 /*virtual*/ bool USBHostPhs::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
00118 {
00119     if (!ports_found &&
00120         CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
00121         port_intf = intf_nb;
00122         ports_found = true;
00123         return true;
00124     }
00125     return false;
00126 }
00127 
00128 /*virtual*/ bool USBHostPhs::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
00129 {
00130     if (ports_found && (intf_nb == port_intf)) {
00131         if (type == BULK_ENDPOINT)
00132             return true;
00133     }
00134     return false;
00135 }
00136 
00137 //------------------------------------------------------------------------------
00138 
00139 #define SET_LINE_CODING 0x20
00140 
00141 USBHostPhsPort::USBHostPhsPort() : cb_tx_en(false), cb_rx_en(false), listener(NULL)
00142 {
00143     init();
00144     reset();
00145 }
00146 
00147 void USBHostPhsPort::init(void)
00148 {
00149     host = NULL;
00150     dev = NULL;
00151     serial_intf = NULL;
00152     size_bulk_in = 0;
00153     size_bulk_out = 0;
00154     bulk_in = NULL;
00155     bulk_out = NULL;
00156     line_coding.baudrate = 921600;
00157     line_coding.data_bits = 8;
00158     line_coding.parity = None;
00159     line_coding.stop_bits = 1;
00160 }
00161 
00162 void USBHostPhsPort::connect(USBHost* _host, USBDeviceConnected * _dev,
00163         uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out)
00164 {
00165     host = _host;
00166     dev = _dev;
00167     serial_intf = _serial_intf;
00168     bulk_in = _bulk_in;
00169     bulk_out = _bulk_out;
00170 
00171   max_out_size = bulk_out->getSize();
00172   if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
00173   {
00174     max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
00175   }
00176 
00177     USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf);
00178     dev->setName("Serial", serial_intf);
00179     host->registerDriver(dev, serial_intf, this, &USBHostPhsPort::init);
00180     baud(921600);
00181     size_bulk_in = bulk_in->getSize();
00182     size_bulk_out = bulk_out->getSize();
00183     bulk_in->attach(this, &USBHostPhsPort::rxHandler);
00184     bulk_out->attach(this, &USBHostPhsPort::txHandler);
00185 
00186   readPacket(); //Start receiving data
00187 }
00188 
00189 void USBHostPhsPort::rxHandler() {
00190   if (((USBEndpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
00191   {
00192     buf_in_read_pos = 0;
00193     buf_in_len = ((USBEndpoint *) bulk_in)->getLengthTransferred(); //Update length
00194     //lock_rx.unlock();
00195     rx_mtx.lock();
00196     lock_rx = false; //Transmission complete
00197     if(cb_rx_en)
00198     {
00199       rx_mtx.unlock();
00200       listener->readable(); //Call handler from the IRQ context
00201       //readPacket() should be called by the handler subsequently once the buffer has been emptied
00202     }
00203     else
00204     {
00205       cb_rx_pending = true; //Queue the callback
00206       rx_mtx.unlock();
00207     }
00208 
00209   }
00210   else //Error, try reading again
00211   {
00212     //lock_rx.unlock();
00213     DBG("Trying again");
00214     readPacket();
00215   }
00216 }
00217 
00218 void USBHostPhsPort::txHandler() {
00219   if (((USBEndpoint *) bulk_out)->getState() == USB_TYPE_IDLE) //Success
00220   {
00221     tx_mtx.lock();
00222     buf_out_len = 0; //Reset length
00223     lock_tx = false; //Transmission complete
00224     //lock_tx.unlock();
00225     if(cb_tx_en)
00226     {
00227       tx_mtx.unlock();
00228       listener->writeable(); //Call handler from the IRQ context
00229       //writePacket() should be called by the handler subsequently once the buffer has been filled
00230     }
00231     else
00232     {
00233       cb_tx_pending = true; //Queue the callback
00234       tx_mtx.unlock();
00235     }
00236   }
00237   else //Error, try reading again
00238   {
00239     //lock_tx.unlock();
00240     writePacket();
00241   }
00242 }
00243 
00244 void USBHostPhsPort::baud(int baudrate) {
00245     line_coding.baudrate = baudrate;
00246     format(line_coding.data_bits, (Parity)line_coding.parity, line_coding.stop_bits);
00247 }
00248 
00249 void USBHostPhsPort::format(int bits, Parity parity, int stop_bits) {
00250     line_coding.data_bits = bits;
00251     line_coding.parity = parity;
00252     line_coding.stop_bits = (stop_bits == 1) ? 0 : 2;
00253 
00254     // set line coding
00255     host->controlWrite( dev,
00256                         USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
00257                         SET_LINE_CODING,
00258                         0, serial_intf, (uint8_t *)&line_coding, 7);
00259 }
00260 
00261 
00262 void USBHostPhsPort::reset()
00263 {
00264   tx_mtx.lock();
00265   rx_mtx.lock();
00266 
00267   buf_out_len = 0;
00268   max_out_size = 0;
00269   lock_tx = false;
00270   cb_tx_pending = false;
00271 
00272   buf_in_len = 0;
00273   buf_in_read_pos = 0;
00274   lock_rx = false;
00275   cb_rx_pending = false;
00276   
00277   tx_mtx.unlock();
00278   rx_mtx.unlock();
00279 }
00280 
00281 int USBHostPhsPort::readPacket()
00282 {
00283   DBG("Read packet on %p", this);
00284   rx_mtx.lock();
00285   if(lock_rx)
00286   {
00287     ERR("Fail");
00288     rx_mtx.unlock();
00289     return -1;
00290   }
00291   
00292   if( bulk_in == NULL )
00293   {
00294     WARN("Port is disconnected");
00295     rx_mtx.unlock();
00296     return -1;
00297   }
00298 
00299   lock_rx = true; //Receiving
00300   rx_mtx.unlock();
00301 //  DBG("readPacket");
00302   //lock_rx.lock();
00303   USB_TYPE res = host->bulkRead(dev, (USBEndpoint *)bulk_in, buf_in, ((USBEndpoint *)bulk_in)->getSize(), false); //Queue transfer
00304 #if __DEBUG__ >= 5
00305   printf(" - bulkRead:");
00306   for (int i = 0; i < buf_in_len; i ++) {
00307     if (buf_in[i] >= 0x20 && buf_in[i] < 0x7f) {
00308       printf(" %c", buf_in[i]);
00309     } else {
00310       printf(" %02x", buf_in[i]);
00311     }
00312   }
00313   printf("\r\n");
00314 #endif
00315   if(res != USB_TYPE_PROCESSING)
00316   {
00317     //lock_rx.unlock();
00318     ERR("host->bulkRead() returned %d", res);
00319     Thread::wait(100);
00320     return -1;
00321   }
00322   return 0;
00323 }
00324 
00325 int USBHostPhsPort::writePacket()
00326 {
00327   tx_mtx.lock();
00328   if(lock_tx)
00329   {
00330     ERR("Fail");
00331     tx_mtx.unlock();
00332     return -1;
00333   }
00334   
00335   if( bulk_out == NULL )
00336   {
00337     WARN("Port is disconnected");
00338     tx_mtx.unlock();
00339     return -1;
00340   }
00341 
00342   lock_tx = true; //Transmitting
00343   tx_mtx.unlock();
00344 //  DBG("writePacket");
00345 
00346   //lock_tx.lock();
00347   USB_TYPE res = host->bulkWrite(dev, (USBEndpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer
00348 #if __DEBUG__ >= 5
00349   printf(" - bulkWrite:");
00350   for (int i = 0; i < buf_out_len; i ++) {
00351     if (buf_out[i] >= 0x20 && buf_out[i] < 0x7f) {
00352       printf(" %c", buf_out[i]);
00353     } else {
00354       printf(" %02x", buf_out[i]);
00355     }
00356   }
00357   printf("\r\n");
00358 #endif
00359   if(res != USB_TYPE_PROCESSING)
00360   {
00361     //lock_tx.unlock();
00362     ERR("host->bulkWrite() returned %d", res);
00363     Thread::wait(100);
00364     return -1;
00365   }
00366   return 0;
00367 }
00368 
00369 int USBHostPhsPort::putc(int c)
00370 {
00371   tx_mtx.lock();
00372   if(!lock_tx)
00373   {
00374     if(buf_out_len < max_out_size)
00375     {
00376       buf_out[buf_out_len] = (uint8_t)c;
00377       buf_out_len++;
00378     }
00379   }
00380   else
00381   {
00382     ERR("CAN'T WRITE!");
00383   }
00384   tx_mtx.unlock();
00385   return c;
00386 }
00387 
00388 int USBHostPhsPort::getc()
00389 {
00390   rx_mtx.lock();
00391   int c = 0;
00392   if(!lock_rx)
00393   {
00394     if(buf_in_read_pos < buf_in_len)
00395     {
00396       c = (int)buf_in[buf_in_read_pos];
00397       buf_in_read_pos++;
00398     }
00399   }
00400   else
00401   {
00402     ERR("CAN'T READ!");
00403   }
00404   rx_mtx.unlock();
00405   return c;
00406 }
00407 
00408 int USBHostPhsPort::readable()
00409 {
00410   rx_mtx.lock();
00411   if (lock_rx)
00412   {
00413     rx_mtx.unlock();
00414     return 0;
00415   }
00416 
00417  /* if( !lock_rx.trylock() )
00418   {
00419     return 0;
00420   }*/
00421   int res = buf_in_len - buf_in_read_pos;
00422   //lock_rx.unlock();
00423   rx_mtx.unlock();
00424   return res;
00425 }
00426 
00427 int USBHostPhsPort::writeable()
00428 {
00429   tx_mtx.lock();
00430   if (lock_tx)
00431   {
00432     tx_mtx.unlock();
00433     return 0;
00434   }
00435 
00436   /*if( !lock_tx.trylock() )
00437   {
00438     return 0;
00439   }*/
00440   int res = max_out_size - buf_out_len;
00441   tx_mtx.unlock();
00442  //lock_tx.unlock();
00443   return res;
00444 }
00445 
00446 void USBHostPhsPort::attach(IUSBHostSerialListener* pListener)
00447 {
00448   if(pListener == NULL)
00449   {
00450     setupIrq(false, IUSBHostSerial::RxIrq);
00451     setupIrq(false, IUSBHostSerial::TxIrq);
00452   }
00453   listener = pListener;
00454   if(pListener != NULL)
00455   {
00456     setupIrq(true, IUSBHostSerial::RxIrq);
00457     setupIrq(true, IUSBHostSerial::TxIrq);
00458   }
00459 }
00460 
00461 void USBHostPhsPort::setupIrq(bool en, IUSBHostSerial::IrqType irq /*= RxIrq*/)
00462 {
00463   switch(irq)
00464   {
00465   case IUSBHostSerial::RxIrq:
00466     rx_mtx.lock();
00467     cb_rx_en = en;
00468     if(en && cb_rx_pending)
00469     {
00470       cb_rx_pending = false;
00471       rx_mtx.unlock();
00472       listener->readable(); //Process the interrupt that was raised
00473     }
00474     else
00475     {
00476       rx_mtx.unlock();
00477     }
00478     break;
00479   case IUSBHostSerial::TxIrq:
00480     tx_mtx.lock();
00481     cb_tx_en = en;
00482     if(en && cb_tx_pending)
00483     {
00484       cb_tx_pending = false;
00485       tx_mtx.unlock();
00486       listener->writeable(); //Process the interrupt that was raised
00487     }
00488     else
00489     {
00490       tx_mtx.unlock();
00491     }
00492     break;
00493   }
00494 }