1 /* 2 * Copyright 2012, Adrien Destugues, pulkomandy@gmail.com 3 * Distributed under the terms of the MIT licence. 4 */ 5 6 7 #include "SerialApp.h" 8 9 #include <stdio.h> 10 #include <string.h> 11 12 #include <Directory.h> 13 #include <Entry.h> 14 #include <File.h> 15 16 #include "SerialWindow.h" 17 18 19 SerialApp::SerialApp() 20 : BApplication(SerialApp::kApplicationSignature) 21 , fLogFile(NULL) 22 { 23 fWindow = new SerialWindow(); 24 25 fSerialLock = create_sem(0, "Serial port lock"); 26 thread_id id = spawn_thread(PollSerial, "Serial port poller", 27 B_LOW_PRIORITY, this); 28 resume_thread(id); 29 } 30 31 32 SerialApp::~SerialApp() 33 { 34 delete fLogFile; 35 } 36 37 38 void SerialApp::ReadyToRun() 39 { 40 fWindow->Show(); 41 } 42 43 44 void SerialApp::MessageReceived(BMessage* message) 45 { 46 switch(message->what) 47 { 48 case kMsgOpenPort: 49 { 50 const char* portName; 51 if(message->FindString("port name", &portName) == B_OK) 52 { 53 fSerialPort.Open(portName); 54 release_sem(fSerialLock); 55 } else { 56 fSerialPort.Close(); 57 } 58 break; 59 } 60 case kMsgDataRead: 61 { 62 // forward the message to the window, which will display the 63 // incoming data 64 fWindow->PostMessage(message); 65 66 if (fLogFile) 67 { 68 const char* bytes; 69 ssize_t length; 70 message->FindData("data", B_RAW_TYPE, (const void**)&bytes, 71 &length); 72 if(fLogFile->Write(bytes, length) != length) 73 { 74 // TODO error handling 75 } 76 } 77 78 break; 79 } 80 case kMsgDataWrite: 81 { 82 const char* bytes; 83 ssize_t size; 84 85 message->FindData("data", B_RAW_TYPE, (const void**)&bytes, &size); 86 87 if (bytes[0] == '\n') { 88 size = 2; 89 bytes = "\r\n"; 90 } 91 fSerialPort.Write(bytes, size); 92 break; 93 } 94 case kMsgLogfile: 95 { 96 entry_ref parent; 97 const char* filename; 98 99 if (message->FindRef("directory", &parent) == B_OK 100 && message->FindString("name", &filename) == B_OK) 101 { 102 delete fLogFile; 103 BDirectory directory(&parent); 104 fLogFile = new BFile(&directory, filename, 105 B_WRITE_ONLY | B_CREATE_FILE | B_OPEN_AT_END); 106 status_t error = fLogFile->InitCheck(); 107 if(error != B_OK) 108 { 109 puts(strerror(error)); 110 } 111 } else { 112 debugger("Invalid BMessage received"); 113 } 114 } 115 case kMsgSettings: 116 { 117 int32 baudrate; 118 stop_bits stopBits; 119 data_bits dataBits; 120 parity_mode parity; 121 uint32 flowcontrol; 122 123 if(message->FindInt32("databits", (int32*)&dataBits) == B_OK) 124 fSerialPort.SetDataBits(dataBits); 125 126 if(message->FindInt32("stopbits", (int32*)&stopBits) == B_OK) 127 fSerialPort.SetStopBits(stopBits); 128 129 if(message->FindInt32("parity", (int32*)&parity) == B_OK) 130 fSerialPort.SetParityMode(parity); 131 132 if(message->FindInt32("flowcontrol", (int32*)&flowcontrol) == B_OK) 133 fSerialPort.SetFlowControl(flowcontrol); 134 135 if(message->FindInt32("baudrate", &baudrate) == B_OK) { 136 data_rate rate; 137 switch(baudrate) { 138 case 50: 139 rate = B_50_BPS; 140 break; 141 case 75: 142 rate = B_75_BPS; 143 break; 144 case 110: 145 rate = B_110_BPS; 146 break; 147 case 134: 148 rate = B_134_BPS; 149 break; 150 case 150: 151 rate = B_150_BPS; 152 break; 153 case 200: 154 rate = B_200_BPS; 155 break; 156 case 300: 157 rate = B_300_BPS; 158 break; 159 case 600: 160 rate = B_600_BPS; 161 break; 162 case 1200: 163 rate = B_1200_BPS; 164 break; 165 case 1800: 166 rate = B_1800_BPS; 167 break; 168 case 2400: 169 rate = B_2400_BPS; 170 break; 171 case 4800: 172 rate = B_4800_BPS; 173 break; 174 case 9600: 175 rate = B_9600_BPS; 176 break; 177 case 19200: 178 rate = B_19200_BPS; 179 break; 180 case 31250: 181 rate = B_31250_BPS; 182 break; 183 case 38400: 184 rate = B_38400_BPS; 185 break; 186 case 57600: 187 rate = B_57600_BPS; 188 break; 189 case 115200: 190 rate = B_115200_BPS; 191 break; 192 case 230400: 193 rate = B_230400_BPS; 194 break; 195 default: 196 rate = B_0_BPS; 197 break; 198 } 199 fSerialPort.SetDataRate(rate); 200 } 201 202 break; 203 } 204 default: 205 BApplication::MessageReceived(message); 206 } 207 } 208 209 210 /* static */ 211 status_t SerialApp::PollSerial(void*) 212 { 213 SerialApp* application = (SerialApp*)be_app; 214 char buffer[256]; 215 216 for(;;) 217 { 218 ssize_t bytesRead; 219 220 bytesRead = application->fSerialPort.Read(buffer, 256); 221 if (bytesRead == B_FILE_ERROR) 222 { 223 // Port is not open - wait for it and start over 224 acquire_sem(application->fSerialLock); 225 } else if (bytesRead > 0) { 226 // We read something, forward it to the app for handling 227 BMessage* serialData = new BMessage(kMsgDataRead); 228 serialData->AddData("data", B_RAW_TYPE, buffer, bytesRead); 229 be_app_messenger.SendMessage(serialData); 230 } 231 } 232 233 // Should not reach this line anyway... 234 return B_OK; 235 } 236 237 const char* SerialApp::kApplicationSignature 238 = "application/x-vnd.haiku.SerialConnect"; 239 240 241 int main(int argc, char** argv) 242 { 243 SerialApp app; 244 app.Run(); 245 } 246