1 /// 2 module serialport.block; 3 4 import serialport.base; 5 6 /// 7 class SerialPortBlk : SerialPort 8 { 9 public: 10 /++ Construct SerialPortBlk 11 12 See_Also: SerialPort.this 13 +/ 14 this(string exmode) { super(exmode); } 15 16 /// ditto 17 this(string port, string mode) { super(port, mode); } 18 19 /// ditto 20 this(string port, uint baudRate) { super(port, baudRate); } 21 22 /// ditto 23 this(string port, uint baudRate, string mode) 24 { super(port, baudRate, mode); } 25 26 /// ditto 27 this(string port, Config conf) { super(port, conf); } 28 29 @property 30 { 31 const 32 { 33 /// 34 Duration readTimeout() { return _readTimeout; } 35 /// 36 Duration readTimeoutMult() { return _readTimeoutMult; } 37 /// 38 Duration writeTimeout() { return _writeTimeout; } 39 /// 40 Duration writeTimeoutMult() { return _writeTimeoutMult; } 41 } 42 43 /// 44 void readTimeout(Duration tm) 45 { 46 _readTimeout = tm; 47 version (Windows) updTimeouts(); 48 } 49 50 /// 51 void readTimeoutMult(Duration tm) 52 { 53 _readTimeoutMult = tm; 54 version (Windows) updTimeouts(); 55 } 56 57 /// 58 void writeTimeout(Duration tm) 59 { 60 _writeTimeout = tm; 61 version (Windows) updTimeouts(); 62 } 63 64 /// 65 void writeTimeoutMult(Duration tm) 66 { 67 _writeTimeout = tm; 68 version (Windows) updTimeouts(); 69 } 70 } 71 72 override void[] read(void[] buf) 73 { 74 if (closed) throw new PortClosedException(port); 75 76 version (Posix) 77 { 78 fd_set sset; 79 FD_ZERO(&sset); 80 FD_SET(_handle, &sset); 81 82 Duration ttm = buf.length * readTimeoutMult + readTimeout; 83 84 timeval ctm; 85 ctm.tv_sec = cast(int)(ttm.total!"seconds"); 86 enum US_PER_MS = 1000; 87 ctm.tv_usec = cast(int)(ttm.split().msecs * US_PER_MS); 88 89 const rv = select(_handle + 1, &sset, null, null, &ctm); 90 if (rv == -1) 91 throw new SysCallException("select", errno); 92 else if (rv == 0) 93 throw new TimeoutException(port); 94 95 const res = posixRead(handle, buf.ptr, buf.length); 96 if (res < 0) 97 throw new ReadException(port, text("errno ", errno)); 98 } 99 else 100 { 101 uint res; 102 103 if (!ReadFile(handle, buf.ptr, cast(uint)buf.length, &res, null)) 104 throw new ReadException(port, text("error ", GetLastError())); 105 106 if (res == 0) 107 throw new TimeoutException(port); 108 } 109 110 return buf[0..res]; 111 } 112 113 override ptrdiff_t write(const(void[]) arr) 114 { 115 if (closed) throw new PortClosedException(port); 116 117 version (Posix) 118 { 119 size_t written; 120 const ttm = arr.length * writeTimeoutMult + writeTimeout; 121 const full = StopWatch(AutoStart.yes); 122 while (written < arr.length) 123 { 124 if (full.peek > ttm) 125 throw new TimeoutException(port); 126 127 const res = posixWrite(_handle, arr[written..$].ptr, arr.length - written); 128 129 if (res < 0) 130 throw new WriteException(port, text("errno ", errno)); 131 132 written += res; 133 } 134 } 135 else 136 { 137 uint written; 138 139 if (!WriteFile(_handle, arr.ptr, cast(uint)arr.length, &written, null)) 140 throw new WriteException(port, text("error ", GetLastError())); 141 142 if (arr.length != written) 143 throw new TimeoutException(port); 144 } 145 146 return written; 147 } 148 149 protected: 150 151 Duration _writeTimeout = 1.seconds, 152 _writeTimeoutMult = Duration.zero, 153 _readTimeout = 1.seconds, 154 _readTimeoutMult = Duration.zero 155 ; 156 157 version (Windows) 158 { 159 override void updTimeouts() 160 { 161 setTimeouts(0, cast(DWORD)readTimeoutMult.total!"msecs", 162 cast(DWORD)readTimeout.total!"msecs", 163 cast(DWORD)writeTimeoutMult.total!"msecs", 164 cast(DWORD)writeTimeout.total!"msecs"); 165 } 166 } 167 168 version (Posix) 169 { 170 override void posixSetup(Config conf) 171 { 172 openPort(); 173 174 if (fcntl(_handle, F_SETFL, 0) == -1) // disable O_NONBLOCK 175 throw new SysCallException("fcntl", errno); 176 177 initialConfig(conf); 178 } 179 } 180 }