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
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 }
Generated on Wed Jul 13 2022 01:40:22 by 1.7.2