local fork
Dependencies: Socket USBHostWANDongle_bleedingedge lwip-sys lwip
Fork of VodafoneUSBModem_bleedingedge by
USBSerialStream.cpp
00001 /* USBSerialStream.cpp */ 00002 /* Copyright (C) 2012 mbed.org, MIT License 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00005 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00006 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00007 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in all copies or 00011 * substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00014 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00015 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00016 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00018 */ 00019 00020 00021 00022 #define __DEBUG__ 0 00023 #ifndef __MODULE__ 00024 #define __MODULE__ "USBSerialStream.cpp" 00025 #endif 00026 00027 #include "core/fwk.h" 00028 00029 #include <cstring> 00030 00031 #include "USBSerialStream.h" 00032 00033 USBSerialStream::USBSerialStream(IUSBHostSerial& serial) : m_serial(serial), m_serialTxFifoEmpty(true), 00034 m_availableSphre(1), m_spaceSphre(1), m_inBuf() 00035 { 00036 m_availableSphre.wait(); 00037 m_spaceSphre.wait(); 00038 //Attach interrupts 00039 m_serial.attach(this); 00040 } 00041 00042 /*virtual*/ USBSerialStream::~USBSerialStream() 00043 { 00044 m_serial.attach(NULL); 00045 } 00046 00047 //0 for non-blocking (returns immediately), -1 for infinite blocking 00048 /*virtual*/ int USBSerialStream::read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout/*=osWaitForever*/) 00049 { 00050 uint8_t *bufPointerCopy = buf; 00051 DBG("Trying to read at most %d chars", maxLength); 00052 int ret = waitAvailable(timeout); 00053 if(ret) 00054 { 00055 WARN("Error %d while waiting for incoming data", ret); 00056 return ret; 00057 } 00058 int a = available(); //Prevent macro issues 00059 int readLen = MIN( a, maxLength ); 00060 *pLength = readLen; 00061 00062 00063 setupReadableISR(false); 00064 while(readLen--) 00065 { 00066 m_inBuf.dequeue(buf); 00067 buf++; 00068 } 00069 setupReadableISR(true); 00070 //printBuffer(bufPointerCopy,*pLength,true); // XXX 00071 00072 return OK; 00073 } 00074 00075 /*virtual*/ size_t USBSerialStream::available() 00076 { 00077 setupReadableISR(false); //m_inBuf.available() is not reentrant 00078 size_t len = m_inBuf.available(); 00079 setupReadableISR(true); 00080 return len; 00081 } 00082 00083 /*virtual*/ int USBSerialStream::waitAvailable(uint32_t timeout/*=osWaitForever*/) //Wait for data to be available 00084 { 00085 int ret; 00086 if(available()) //Is data already available? 00087 { 00088 while( m_availableSphre.wait(0) > 0 ); //Clear the queue as data is available 00089 return OK; 00090 } 00091 00092 DBG("Waiting for data availability %d ms (-1 is infinite)", timeout); 00093 ret = m_availableSphre.wait(timeout); //Wait for data to arrive or for abort 00094 if(ret <= 0) 00095 { 00096 DBG("Timeout"); 00097 return NET_TIMEOUT; 00098 } 00099 if(!m_inBuf.available()) //Even if abort has been called, return that data is available 00100 { 00101 DBG("Aborted"); 00102 return NET_INTERRUPTED; 00103 } 00104 DBG("Finished waiting"); 00105 while( m_availableSphre.wait(0) > 0 ); //Clear the queue as data is available 00106 return OK; 00107 } 00108 00109 /*virtual*/ int USBSerialStream::abortRead() //Abort current reading (or waiting) operation 00110 { 00111 if( /*!available()*/true ) //If there is data pending, no need to abort 00112 { 00113 m_availableSphre.release(); //Force exiting the waiting state 00114 } 00115 else 00116 { 00117 DBG("Serial is readable"); ; 00118 } 00119 return OK; 00120 } 00121 00122 void USBSerialStream::setupReadableISR(bool en) 00123 { 00124 m_serial.setupIrq(en, IUSBHostSerial::RxIrq); 00125 } 00126 00127 void USBSerialStream::readable() //Callback from m_serial when new data is available 00128 { 00129 while(m_serial.readable()) 00130 { 00131 m_inBuf.queue(m_serial.getc()); 00132 } 00133 m_serial.readPacket(); //Start read of next packet 00134 m_availableSphre.release(); //Force exiting the waiting state 00135 } 00136 00137 00138 00139 //0 for non-blocking (returns immediately), -1 for infinite blocking 00140 /*virtual*/ int USBSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=-1*/) 00141 { 00142 //printBuffer(buf,length,false); // XXX 00143 DBG("Trying to write %d chars", length); 00144 do 00145 { 00146 int ret = waitSpace(timeout); 00147 if(ret) 00148 { 00149 WARN("Error %d while waiting for space", ret); 00150 return ret; 00151 } 00152 int s = space(); //Prevent macro issues 00153 int writeLen = MIN( s, length ); 00154 DBG("Writing %d chars", writeLen); 00155 setupWriteableISR(false); 00156 while(writeLen) 00157 { 00158 m_outBuf.queue(*buf); 00159 buf++; 00160 length--; 00161 writeLen--; 00162 } 00163 //If m_serial tx fifo is empty we need to start the packet write 00164 if( m_outBuf.available() && m_serialTxFifoEmpty ) 00165 { 00166 writeable(); 00167 } 00168 setupWriteableISR(true); 00169 } while(length); 00170 DBG("Write successful"); 00171 return OK; 00172 } 00173 00174 /*virtual*/ size_t USBSerialStream::space() 00175 { 00176 setupWriteableISR(false); //m_outBuf.available() is not reentrant 00177 size_t len = CIRCBUF_SIZE - m_outBuf.available(); 00178 setupWriteableISR(true); 00179 return len; 00180 } 00181 00182 /*virtual*/ int USBSerialStream::waitSpace(uint32_t timeout/*=-1*/) //Wait for space to be available 00183 { 00184 int ret; 00185 if(space()) //Is still space already left? 00186 { 00187 while( m_spaceSphre.wait(0) > 0); //Clear the queue as space is available 00188 return OK; 00189 } 00190 00191 DBG("Waiting for data space %d ms (-1 is infinite)", timeout); 00192 ret = m_spaceSphre.wait(timeout); //Wait for space to be made or for abort 00193 if(ret <= 0) 00194 { 00195 DBG("Timeout"); 00196 return NET_TIMEOUT; 00197 } 00198 if(!space()) //Even if abort has been called, return that space is available 00199 { 00200 DBG("Aborted"); 00201 return NET_INTERRUPTED; 00202 } 00203 while( m_spaceSphre.wait(0) > 0); //Clear the queue as space is available 00204 return OK; 00205 } 00206 00207 /*virtual*/ int USBSerialStream::abortWrite() //Abort current writing (or waiting) operation 00208 { 00209 if( !space() ) //If there is space left, no need to abort 00210 { 00211 m_spaceSphre.release(); //Force exiting the waiting state 00212 } 00213 return OK; 00214 } 00215 00216 void USBSerialStream::setupWriteableISR(bool en) 00217 { 00218 m_serial.setupIrq(en, IUSBHostSerial::TxIrq); 00219 } 00220 00221 void USBSerialStream::writeable() //Callback from m_serial when new space is available 00222 { 00223 if(m_outBuf.isEmpty()) 00224 { 00225 m_serialTxFifoEmpty = true; 00226 } 00227 else 00228 { 00229 m_serialTxFifoEmpty = false; 00230 while(m_serial.writeable() && !m_outBuf.isEmpty()) 00231 { 00232 uint8_t c; 00233 m_outBuf.dequeue(&c); 00234 m_serial.putc((char)c); 00235 } 00236 m_serial.writePacket(); //Start packet write 00237 } 00238 if(!m_outBuf.isFull()) 00239 { 00240 m_spaceSphre.release(); //Force exiting the waiting state 00241 } 00242 }
Generated on Tue Jul 12 2022 21:41:40 by 1.7.2