1 /// 2 module serialport.block; 3 4 import serialport.base; 5 6 /// Blocking work serialport 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 override void[] read(void[] buf, CanRead cr=CanRead.allOrNothing) 30 { 31 if (closed) throwPortClosedException(port); 32 33 version (Posix) 34 { 35 if (cr == CanRead.allOrNothing) 36 setCC([cast(ubyte)min(buf.length, 255), 0]); 37 else setCC([1, 0]); 38 39 ssize_t res = 0; 40 auto ttm = buf.length * readTimeoutMult + readTimeout; 41 auto sw = StopWatch(AutoStart.yes); 42 while (ttm > Duration.zero) 43 { 44 ttm -= sw.peek; 45 sw.reset(); 46 47 fd_set sset; 48 FD_ZERO(&sset); 49 FD_SET(_handle, &sset); 50 51 timeval ctm; 52 ctm.tv_sec = cast(int)(ttm.total!"seconds"); 53 enum US_PER_MS = 1000; 54 ctm.tv_usec = cast(int)(ttm.split().msecs * US_PER_MS); 55 56 const rv = select(_handle + 1, &sset, null, null, &ctm); 57 if (rv < 0) throwSysCallException(port, "select", errno); 58 59 if (rv == 0) break; 60 61 const r = posixRead(_handle, buf.ptr+res, buf.length-res); 62 if (r < 0) throwReadException(port, "posix read", errno); 63 res += r; 64 if (res == buf.length) return buf; 65 } 66 } 67 else 68 { 69 uint res; 70 71 if (!ReadFile(handle, buf.ptr, cast(uint)buf.length, &res, null)) 72 throwReadException(port, "win read", GetLastError()); 73 } 74 75 checkAbility(cr, res, buf.length); 76 77 return buf[0..res]; 78 } 79 80 override void write(const(void[]) arr) 81 { 82 if (closed) throwPortClosedException(port); 83 84 version (Posix) 85 { 86 size_t written; 87 const ttm = arr.length * writeTimeoutMult + writeTimeout; 88 const full = StopWatch(AutoStart.yes); 89 while (written < arr.length) 90 { 91 if (full.peek > ttm) 92 throwTimeoutException(port, "write timeout"); 93 94 const res = posixWrite(_handle, arr[written..$].ptr, arr.length - written); 95 96 if (res < 0) 97 throwWriteException(port, "posix write", errno); 98 99 written += res; 100 } 101 } 102 else 103 { 104 uint written; 105 106 if (!WriteFile(_handle, arr.ptr, cast(uint)arr.length, &written, null)) 107 throwWriteException(port, "win write", GetLastError()); 108 109 if (arr.length != written) 110 throwTimeoutException(port, "write timeout"); 111 } 112 } 113 114 protected: 115 116 override void[] m_read(void[]) @nogc 117 { assert(0, "disable m_read for blocking"); } 118 override size_t m_write(const(void)[]) @nogc 119 { assert(0, "disable m_write for blocking"); } 120 121 override void updateTimeouts() @nogc { version (Windows) updTimeouts(); } 122 123 version (Windows) 124 { 125 override void updTimeouts() @nogc 126 { 127 setTimeouts(0, cast(DWORD)readTimeoutMult.total!"msecs", 128 cast(DWORD)readTimeout.total!"msecs", 129 cast(DWORD)writeTimeoutMult.total!"msecs", 130 cast(DWORD)writeTimeout.total!"msecs"); 131 } 132 } 133 134 version (Posix) 135 { 136 override void posixSetup(Config conf) 137 { 138 openPort(); 139 140 if (fcntl(_handle, F_SETFL, 0) == -1) // disable O_NONBLOCK 141 throwSysCallException(port, "fcntl", errno); 142 143 setCC([1,0]); 144 145 initialConfig(conf); 146 } 147 } 148 }