1dae0a4e0SAdrien Destugues - PulkoMandy /* 2dae0a4e0SAdrien Destugues - PulkoMandy * Copyright 2012, Adrien Destugues, pulkomandy@gmail.com 3dae0a4e0SAdrien Destugues - PulkoMandy * Distributed under the terms of the MIT licence. 4dae0a4e0SAdrien Destugues - PulkoMandy */ 5dae0a4e0SAdrien Destugues - PulkoMandy 6dae0a4e0SAdrien Destugues - PulkoMandy 7dae0a4e0SAdrien Destugues - PulkoMandy #include "SerialApp.h" 8dae0a4e0SAdrien Destugues - PulkoMandy 9469e6cd2SAdrien Destugues - PulkoMandy #include <stdio.h> 10469e6cd2SAdrien Destugues - PulkoMandy #include <string.h> 11469e6cd2SAdrien Destugues - PulkoMandy 12469e6cd2SAdrien Destugues - PulkoMandy #include <Directory.h> 13469e6cd2SAdrien Destugues - PulkoMandy #include <Entry.h> 14469e6cd2SAdrien Destugues - PulkoMandy #include <File.h> 15*ccc6b9beSAdrien Destugues #include <FindDirectory.h> 16*ccc6b9beSAdrien Destugues #include <Path.h> 17469e6cd2SAdrien Destugues - PulkoMandy 18dae0a4e0SAdrien Destugues - PulkoMandy #include "SerialWindow.h" 19dae0a4e0SAdrien Destugues - PulkoMandy 20dae0a4e0SAdrien Destugues - PulkoMandy 21dae0a4e0SAdrien Destugues - PulkoMandy SerialApp::SerialApp() 22469e6cd2SAdrien Destugues - PulkoMandy : BApplication(SerialApp::kApplicationSignature) 23469e6cd2SAdrien Destugues - PulkoMandy , fLogFile(NULL) 24dae0a4e0SAdrien Destugues - PulkoMandy { 25dae0a4e0SAdrien Destugues - PulkoMandy fWindow = new SerialWindow(); 26dae0a4e0SAdrien Destugues - PulkoMandy 27f441fd03SAdrien Destugues - PulkoMandy fSerialLock = create_sem(0, "Serial port lock"); 28dae0a4e0SAdrien Destugues - PulkoMandy thread_id id = spawn_thread(PollSerial, "Serial port poller", 29dae0a4e0SAdrien Destugues - PulkoMandy B_LOW_PRIORITY, this); 30dae0a4e0SAdrien Destugues - PulkoMandy resume_thread(id); 31dae0a4e0SAdrien Destugues - PulkoMandy } 32dae0a4e0SAdrien Destugues - PulkoMandy 33dae0a4e0SAdrien Destugues - PulkoMandy 34469e6cd2SAdrien Destugues - PulkoMandy SerialApp::~SerialApp() 35469e6cd2SAdrien Destugues - PulkoMandy { 36469e6cd2SAdrien Destugues - PulkoMandy delete fLogFile; 37469e6cd2SAdrien Destugues - PulkoMandy } 38469e6cd2SAdrien Destugues - PulkoMandy 39469e6cd2SAdrien Destugues - PulkoMandy 40dae0a4e0SAdrien Destugues - PulkoMandy void SerialApp::ReadyToRun() 41dae0a4e0SAdrien Destugues - PulkoMandy { 42*ccc6b9beSAdrien Destugues LoadSettings(); 43dae0a4e0SAdrien Destugues - PulkoMandy fWindow->Show(); 44dae0a4e0SAdrien Destugues - PulkoMandy } 45dae0a4e0SAdrien Destugues - PulkoMandy 46dae0a4e0SAdrien Destugues - PulkoMandy 47dae0a4e0SAdrien Destugues - PulkoMandy void SerialApp::MessageReceived(BMessage* message) 48dae0a4e0SAdrien Destugues - PulkoMandy { 49dae0a4e0SAdrien Destugues - PulkoMandy switch(message->what) 50dae0a4e0SAdrien Destugues - PulkoMandy { 51dae0a4e0SAdrien Destugues - PulkoMandy case kMsgOpenPort: 52dae0a4e0SAdrien Destugues - PulkoMandy { 53*ccc6b9beSAdrien Destugues if(message->FindString("port name", &fPortPath) == B_OK) 5404434656SAdrien Destugues - PulkoMandy { 55*ccc6b9beSAdrien Destugues fSerialPort.Open(fPortPath); 56f441fd03SAdrien Destugues - PulkoMandy release_sem(fSerialLock); 5704434656SAdrien Destugues - PulkoMandy } else { 5804434656SAdrien Destugues - PulkoMandy fSerialPort.Close(); 5904434656SAdrien Destugues - PulkoMandy } 60dae0a4e0SAdrien Destugues - PulkoMandy break; 61dae0a4e0SAdrien Destugues - PulkoMandy } 62dae0a4e0SAdrien Destugues - PulkoMandy case kMsgDataRead: 63dae0a4e0SAdrien Destugues - PulkoMandy { 64f441fd03SAdrien Destugues - PulkoMandy // forward the message to the window, which will display the 65f441fd03SAdrien Destugues - PulkoMandy // incoming data 66f441fd03SAdrien Destugues - PulkoMandy fWindow->PostMessage(message); 67469e6cd2SAdrien Destugues - PulkoMandy 68469e6cd2SAdrien Destugues - PulkoMandy if (fLogFile) 69469e6cd2SAdrien Destugues - PulkoMandy { 70469e6cd2SAdrien Destugues - PulkoMandy const char* bytes; 71469e6cd2SAdrien Destugues - PulkoMandy ssize_t length; 72469e6cd2SAdrien Destugues - PulkoMandy message->FindData("data", B_RAW_TYPE, (const void**)&bytes, 73469e6cd2SAdrien Destugues - PulkoMandy &length); 74469e6cd2SAdrien Destugues - PulkoMandy if(fLogFile->Write(bytes, length) != length) 75469e6cd2SAdrien Destugues - PulkoMandy { 76d481cb73SAdrien Destugues - PulkoMandy // TODO error handling 77469e6cd2SAdrien Destugues - PulkoMandy } 78469e6cd2SAdrien Destugues - PulkoMandy } 79469e6cd2SAdrien Destugues - PulkoMandy 80dae0a4e0SAdrien Destugues - PulkoMandy break; 81dae0a4e0SAdrien Destugues - PulkoMandy } 82f441fd03SAdrien Destugues - PulkoMandy case kMsgDataWrite: 83f441fd03SAdrien Destugues - PulkoMandy { 84f441fd03SAdrien Destugues - PulkoMandy const char* bytes; 85f441fd03SAdrien Destugues - PulkoMandy ssize_t size; 86f441fd03SAdrien Destugues - PulkoMandy 8747b44bbeSPhilippe Houdoin message->FindData("data", B_RAW_TYPE, (const void**)&bytes, &size); 88d481cb73SAdrien Destugues - PulkoMandy 89d481cb73SAdrien Destugues - PulkoMandy if (bytes[0] == '\n') { 90d481cb73SAdrien Destugues - PulkoMandy size = 2; 91d481cb73SAdrien Destugues - PulkoMandy bytes = "\r\n"; 92d481cb73SAdrien Destugues - PulkoMandy } 93f441fd03SAdrien Destugues - PulkoMandy fSerialPort.Write(bytes, size); 9404434656SAdrien Destugues - PulkoMandy break; 9504434656SAdrien Destugues - PulkoMandy } 96469e6cd2SAdrien Destugues - PulkoMandy case kMsgLogfile: 97469e6cd2SAdrien Destugues - PulkoMandy { 98469e6cd2SAdrien Destugues - PulkoMandy entry_ref parent; 99469e6cd2SAdrien Destugues - PulkoMandy const char* filename; 100469e6cd2SAdrien Destugues - PulkoMandy 101469e6cd2SAdrien Destugues - PulkoMandy if (message->FindRef("directory", &parent) == B_OK 102469e6cd2SAdrien Destugues - PulkoMandy && message->FindString("name", &filename) == B_OK) 103469e6cd2SAdrien Destugues - PulkoMandy { 104469e6cd2SAdrien Destugues - PulkoMandy delete fLogFile; 105469e6cd2SAdrien Destugues - PulkoMandy BDirectory directory(&parent); 106469e6cd2SAdrien Destugues - PulkoMandy fLogFile = new BFile(&directory, filename, 107469e6cd2SAdrien Destugues - PulkoMandy B_WRITE_ONLY | B_CREATE_FILE | B_OPEN_AT_END); 108469e6cd2SAdrien Destugues - PulkoMandy status_t error = fLogFile->InitCheck(); 109469e6cd2SAdrien Destugues - PulkoMandy if(error != B_OK) 110469e6cd2SAdrien Destugues - PulkoMandy { 111469e6cd2SAdrien Destugues - PulkoMandy puts(strerror(error)); 112469e6cd2SAdrien Destugues - PulkoMandy } 113469e6cd2SAdrien Destugues - PulkoMandy } else { 114469e6cd2SAdrien Destugues - PulkoMandy debugger("Invalid BMessage received"); 115469e6cd2SAdrien Destugues - PulkoMandy } 116469e6cd2SAdrien Destugues - PulkoMandy } 11704434656SAdrien Destugues - PulkoMandy case kMsgSettings: 11804434656SAdrien Destugues - PulkoMandy { 11904434656SAdrien Destugues - PulkoMandy int32 baudrate; 12004434656SAdrien Destugues - PulkoMandy stop_bits stopBits; 12104434656SAdrien Destugues - PulkoMandy data_bits dataBits; 12204434656SAdrien Destugues - PulkoMandy parity_mode parity; 12304434656SAdrien Destugues - PulkoMandy uint32 flowcontrol; 12404434656SAdrien Destugues - PulkoMandy 12504434656SAdrien Destugues - PulkoMandy if(message->FindInt32("databits", (int32*)&dataBits) == B_OK) 12604434656SAdrien Destugues - PulkoMandy fSerialPort.SetDataBits(dataBits); 12704434656SAdrien Destugues - PulkoMandy 12804434656SAdrien Destugues - PulkoMandy if(message->FindInt32("stopbits", (int32*)&stopBits) == B_OK) 12904434656SAdrien Destugues - PulkoMandy fSerialPort.SetStopBits(stopBits); 13004434656SAdrien Destugues - PulkoMandy 13104434656SAdrien Destugues - PulkoMandy if(message->FindInt32("parity", (int32*)&parity) == B_OK) 13204434656SAdrien Destugues - PulkoMandy fSerialPort.SetParityMode(parity); 13304434656SAdrien Destugues - PulkoMandy 13404434656SAdrien Destugues - PulkoMandy if(message->FindInt32("flowcontrol", (int32*)&flowcontrol) == B_OK) 13504434656SAdrien Destugues - PulkoMandy fSerialPort.SetFlowControl(flowcontrol); 13604434656SAdrien Destugues - PulkoMandy 13704434656SAdrien Destugues - PulkoMandy if(message->FindInt32("baudrate", &baudrate) == B_OK) { 13804434656SAdrien Destugues - PulkoMandy data_rate rate; 13904434656SAdrien Destugues - PulkoMandy switch(baudrate) { 14004434656SAdrien Destugues - PulkoMandy case 50: 14104434656SAdrien Destugues - PulkoMandy rate = B_50_BPS; 14204434656SAdrien Destugues - PulkoMandy break; 14304434656SAdrien Destugues - PulkoMandy case 75: 14404434656SAdrien Destugues - PulkoMandy rate = B_75_BPS; 14504434656SAdrien Destugues - PulkoMandy break; 14604434656SAdrien Destugues - PulkoMandy case 110: 14704434656SAdrien Destugues - PulkoMandy rate = B_110_BPS; 14804434656SAdrien Destugues - PulkoMandy break; 14904434656SAdrien Destugues - PulkoMandy case 134: 15004434656SAdrien Destugues - PulkoMandy rate = B_134_BPS; 15104434656SAdrien Destugues - PulkoMandy break; 15204434656SAdrien Destugues - PulkoMandy case 150: 15304434656SAdrien Destugues - PulkoMandy rate = B_150_BPS; 15404434656SAdrien Destugues - PulkoMandy break; 15504434656SAdrien Destugues - PulkoMandy case 200: 15604434656SAdrien Destugues - PulkoMandy rate = B_200_BPS; 15704434656SAdrien Destugues - PulkoMandy break; 15804434656SAdrien Destugues - PulkoMandy case 300: 15904434656SAdrien Destugues - PulkoMandy rate = B_300_BPS; 16004434656SAdrien Destugues - PulkoMandy break; 16104434656SAdrien Destugues - PulkoMandy case 600: 16204434656SAdrien Destugues - PulkoMandy rate = B_600_BPS; 16304434656SAdrien Destugues - PulkoMandy break; 16404434656SAdrien Destugues - PulkoMandy case 1200: 16504434656SAdrien Destugues - PulkoMandy rate = B_1200_BPS; 16604434656SAdrien Destugues - PulkoMandy break; 16704434656SAdrien Destugues - PulkoMandy case 1800: 16804434656SAdrien Destugues - PulkoMandy rate = B_1800_BPS; 16904434656SAdrien Destugues - PulkoMandy break; 17004434656SAdrien Destugues - PulkoMandy case 2400: 17104434656SAdrien Destugues - PulkoMandy rate = B_2400_BPS; 17204434656SAdrien Destugues - PulkoMandy break; 17304434656SAdrien Destugues - PulkoMandy case 4800: 17404434656SAdrien Destugues - PulkoMandy rate = B_4800_BPS; 17504434656SAdrien Destugues - PulkoMandy break; 17604434656SAdrien Destugues - PulkoMandy case 9600: 17704434656SAdrien Destugues - PulkoMandy rate = B_9600_BPS; 17804434656SAdrien Destugues - PulkoMandy break; 17904434656SAdrien Destugues - PulkoMandy case 19200: 18004434656SAdrien Destugues - PulkoMandy rate = B_19200_BPS; 18104434656SAdrien Destugues - PulkoMandy break; 18204434656SAdrien Destugues - PulkoMandy case 31250: 18304434656SAdrien Destugues - PulkoMandy rate = B_31250_BPS; 18404434656SAdrien Destugues - PulkoMandy break; 18504434656SAdrien Destugues - PulkoMandy case 38400: 18604434656SAdrien Destugues - PulkoMandy rate = B_38400_BPS; 18704434656SAdrien Destugues - PulkoMandy break; 18804434656SAdrien Destugues - PulkoMandy case 57600: 18904434656SAdrien Destugues - PulkoMandy rate = B_57600_BPS; 19004434656SAdrien Destugues - PulkoMandy break; 19104434656SAdrien Destugues - PulkoMandy case 115200: 19204434656SAdrien Destugues - PulkoMandy rate = B_115200_BPS; 19304434656SAdrien Destugues - PulkoMandy break; 19404434656SAdrien Destugues - PulkoMandy case 230400: 19504434656SAdrien Destugues - PulkoMandy rate = B_230400_BPS; 19604434656SAdrien Destugues - PulkoMandy break; 19704434656SAdrien Destugues - PulkoMandy default: 19804434656SAdrien Destugues - PulkoMandy rate = B_0_BPS; 19904434656SAdrien Destugues - PulkoMandy break; 20004434656SAdrien Destugues - PulkoMandy } 20104434656SAdrien Destugues - PulkoMandy fSerialPort.SetDataRate(rate); 20204434656SAdrien Destugues - PulkoMandy } 20304434656SAdrien Destugues - PulkoMandy 20404434656SAdrien Destugues - PulkoMandy break; 205f441fd03SAdrien Destugues - PulkoMandy } 206dae0a4e0SAdrien Destugues - PulkoMandy default: 207dae0a4e0SAdrien Destugues - PulkoMandy BApplication::MessageReceived(message); 208dae0a4e0SAdrien Destugues - PulkoMandy } 209dae0a4e0SAdrien Destugues - PulkoMandy } 210dae0a4e0SAdrien Destugues - PulkoMandy 211dae0a4e0SAdrien Destugues - PulkoMandy 212*ccc6b9beSAdrien Destugues bool SerialApp::QuitRequested() 213*ccc6b9beSAdrien Destugues { 214*ccc6b9beSAdrien Destugues if(BApplication::QuitRequested()) { 215*ccc6b9beSAdrien Destugues SaveSettings(); 216*ccc6b9beSAdrien Destugues return true; 217*ccc6b9beSAdrien Destugues } 218*ccc6b9beSAdrien Destugues return false; 219*ccc6b9beSAdrien Destugues } 220*ccc6b9beSAdrien Destugues 221*ccc6b9beSAdrien Destugues 222*ccc6b9beSAdrien Destugues const BString& SerialApp::GetPort() 223*ccc6b9beSAdrien Destugues { 224*ccc6b9beSAdrien Destugues return fPortPath; 225*ccc6b9beSAdrien Destugues } 226*ccc6b9beSAdrien Destugues 227*ccc6b9beSAdrien Destugues 228*ccc6b9beSAdrien Destugues void SerialApp::LoadSettings() 229*ccc6b9beSAdrien Destugues { 230*ccc6b9beSAdrien Destugues BPath path; 231*ccc6b9beSAdrien Destugues find_directory(B_USER_SETTINGS_DIRECTORY, &path); 232*ccc6b9beSAdrien Destugues path.Append("SerialConnect"); 233*ccc6b9beSAdrien Destugues 234*ccc6b9beSAdrien Destugues BFile file(path.Path(), B_READ_ONLY); 235*ccc6b9beSAdrien Destugues BMessage message(kMsgSettings); 236*ccc6b9beSAdrien Destugues if(message.Unflatten(&file) != B_OK) 237*ccc6b9beSAdrien Destugues { 238*ccc6b9beSAdrien Destugues message.AddInt32("parity", fSerialPort.ParityMode()); 239*ccc6b9beSAdrien Destugues message.AddInt32("databits", fSerialPort.DataBits()); 240*ccc6b9beSAdrien Destugues message.AddInt32("stopbits", fSerialPort.StopBits()); 241*ccc6b9beSAdrien Destugues message.AddInt32("baudrate", fSerialPort.DataRate()); 242*ccc6b9beSAdrien Destugues message.AddInt32("flowcontrol", fSerialPort.FlowControl()); 243*ccc6b9beSAdrien Destugues } 244*ccc6b9beSAdrien Destugues 245*ccc6b9beSAdrien Destugues be_app->PostMessage(&message); 246*ccc6b9beSAdrien Destugues fWindow->PostMessage(&message); 247*ccc6b9beSAdrien Destugues } 248*ccc6b9beSAdrien Destugues 249*ccc6b9beSAdrien Destugues 250*ccc6b9beSAdrien Destugues void SerialApp::SaveSettings() 251*ccc6b9beSAdrien Destugues { 252*ccc6b9beSAdrien Destugues BMessage message(kMsgSettings); 253*ccc6b9beSAdrien Destugues message.AddInt32("parity", fSerialPort.ParityMode()); 254*ccc6b9beSAdrien Destugues message.AddInt32("databits", fSerialPort.DataBits()); 255*ccc6b9beSAdrien Destugues message.AddInt32("stopbits", fSerialPort.StopBits()); 256*ccc6b9beSAdrien Destugues message.AddInt32("baudrate", fSerialPort.DataRate()); 257*ccc6b9beSAdrien Destugues message.AddInt32("flowcontrol", fSerialPort.FlowControl()); 258*ccc6b9beSAdrien Destugues 259*ccc6b9beSAdrien Destugues BPath path; 260*ccc6b9beSAdrien Destugues find_directory(B_USER_SETTINGS_DIRECTORY, &path); 261*ccc6b9beSAdrien Destugues path.Append("SerialConnect"); 262*ccc6b9beSAdrien Destugues 263*ccc6b9beSAdrien Destugues BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE); 264*ccc6b9beSAdrien Destugues message.Flatten(&file); 265*ccc6b9beSAdrien Destugues } 266*ccc6b9beSAdrien Destugues 267*ccc6b9beSAdrien Destugues 268dae0a4e0SAdrien Destugues - PulkoMandy /* static */ 269dae0a4e0SAdrien Destugues - PulkoMandy status_t SerialApp::PollSerial(void*) 270dae0a4e0SAdrien Destugues - PulkoMandy { 271dae0a4e0SAdrien Destugues - PulkoMandy SerialApp* application = (SerialApp*)be_app; 272dae0a4e0SAdrien Destugues - PulkoMandy char buffer[256]; 273dae0a4e0SAdrien Destugues - PulkoMandy 274dae0a4e0SAdrien Destugues - PulkoMandy for(;;) 275dae0a4e0SAdrien Destugues - PulkoMandy { 276dae0a4e0SAdrien Destugues - PulkoMandy ssize_t bytesRead; 277dae0a4e0SAdrien Destugues - PulkoMandy 278f441fd03SAdrien Destugues - PulkoMandy bytesRead = application->fSerialPort.Read(buffer, 256); 279dae0a4e0SAdrien Destugues - PulkoMandy if (bytesRead == B_FILE_ERROR) 280dae0a4e0SAdrien Destugues - PulkoMandy { 281dae0a4e0SAdrien Destugues - PulkoMandy // Port is not open - wait for it and start over 282f441fd03SAdrien Destugues - PulkoMandy acquire_sem(application->fSerialLock); 283f441fd03SAdrien Destugues - PulkoMandy } else if (bytesRead > 0) { 284dae0a4e0SAdrien Destugues - PulkoMandy // We read something, forward it to the app for handling 285dae0a4e0SAdrien Destugues - PulkoMandy BMessage* serialData = new BMessage(kMsgDataRead); 286f441fd03SAdrien Destugues - PulkoMandy serialData->AddData("data", B_RAW_TYPE, buffer, bytesRead); 287dae0a4e0SAdrien Destugues - PulkoMandy be_app_messenger.SendMessage(serialData); 288dae0a4e0SAdrien Destugues - PulkoMandy } 289dae0a4e0SAdrien Destugues - PulkoMandy } 29047b44bbeSPhilippe Houdoin 29147b44bbeSPhilippe Houdoin // Should not reach this line anyway... 29247b44bbeSPhilippe Houdoin return B_OK; 293dae0a4e0SAdrien Destugues - PulkoMandy } 294dae0a4e0SAdrien Destugues - PulkoMandy 295dae0a4e0SAdrien Destugues - PulkoMandy const char* SerialApp::kApplicationSignature 296dae0a4e0SAdrien Destugues - PulkoMandy = "application/x-vnd.haiku.SerialConnect"; 297dae0a4e0SAdrien Destugues - PulkoMandy 298dae0a4e0SAdrien Destugues - PulkoMandy 299dae0a4e0SAdrien Destugues - PulkoMandy int main(int argc, char** argv) 300dae0a4e0SAdrien Destugues - PulkoMandy { 301dae0a4e0SAdrien Destugues - PulkoMandy SerialApp app; 302dae0a4e0SAdrien Destugues - PulkoMandy app.Run(); 303dae0a4e0SAdrien Destugues - PulkoMandy } 304