xref: /haiku/src/apps/serialconnect/SerialApp.cpp (revision ccc6b9be5b6527d14bb35b6ce57dcb422c0422f0)
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