SerialConnect: add scripting support
It's now possible to configure the serial port through scripting: hey SerialConnect set databits to 8 hey SerialConnect set parity to even etc. More useful is the ability to connect and disconnect from the port: hey SerialConnect get port # returns "usb0" hey SerialConnect set port to usb0 hey SerialConnect delete port This allows a script to automatically disconnect SerialConnect, do something with the serial port, and then reconnect SerialConnect. This can be used for example to run a bootloader and update a firmware through the same serial port used for debugging, something that's not easily possible on other systems.
This commit is contained in:
parent
600c0527d5
commit
d9e931526c
@ -18,6 +18,49 @@
|
|||||||
#include "SerialWindow.h"
|
#include "SerialWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
static property_info sProperties[] = {
|
||||||
|
{ "baudrate",
|
||||||
|
{ B_GET_PROPERTY, B_SET_PROPERTY, 0 },
|
||||||
|
{ B_DIRECT_SPECIFIER, B_DIRECT_SPECIFIER, 0 },
|
||||||
|
"get or set the baudrate",
|
||||||
|
0, { B_INT32_TYPE }
|
||||||
|
},
|
||||||
|
{ "bits",
|
||||||
|
{ B_GET_PROPERTY, B_SET_PROPERTY, 0 },
|
||||||
|
{ B_DIRECT_SPECIFIER, B_DIRECT_SPECIFIER, 0 },
|
||||||
|
"get or set the number of data bits (7 or 8)",
|
||||||
|
0, { B_INT32_TYPE }
|
||||||
|
},
|
||||||
|
{ "stopbits",
|
||||||
|
{ B_GET_PROPERTY, B_SET_PROPERTY, 0 },
|
||||||
|
{ B_DIRECT_SPECIFIER, B_DIRECT_SPECIFIER, 0 },
|
||||||
|
"get or set the number of stop bits (1 or 2)",
|
||||||
|
0, { B_INT32_TYPE }
|
||||||
|
},
|
||||||
|
{ "parity",
|
||||||
|
{ B_GET_PROPERTY, B_SET_PROPERTY, 0 },
|
||||||
|
{ B_DIRECT_SPECIFIER, B_DIRECT_SPECIFIER, 0 },
|
||||||
|
"get or set the parity (none, even or odd)",
|
||||||
|
0, { B_STRING_TYPE }
|
||||||
|
},
|
||||||
|
{ "flowcontrol",
|
||||||
|
{ B_GET_PROPERTY, B_SET_PROPERTY, 0 },
|
||||||
|
{ B_DIRECT_SPECIFIER, B_DIRECT_SPECIFIER, 0 },
|
||||||
|
"get or set the flow control (hardware, software, both, or none)",
|
||||||
|
0, { B_STRING_TYPE }
|
||||||
|
},
|
||||||
|
{ "port",
|
||||||
|
{ B_GET_PROPERTY, B_SET_PROPERTY, B_DELETE_PROPERTY, 0 },
|
||||||
|
{ B_DIRECT_SPECIFIER, 0 },
|
||||||
|
"get or set the port device",
|
||||||
|
0, { B_STRING_TYPE }
|
||||||
|
},
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const BPropertyInfo SerialApp::kScriptingProperties(sProperties);
|
||||||
|
|
||||||
|
|
||||||
SerialApp::SerialApp()
|
SerialApp::SerialApp()
|
||||||
: BApplication(SerialApp::kApplicationSignature)
|
: BApplication(SerialApp::kApplicationSignature)
|
||||||
, fLogFile(NULL)
|
, fLogFile(NULL)
|
||||||
@ -55,7 +98,7 @@ void SerialApp::MessageReceived(BMessage* message)
|
|||||||
} else {
|
} else {
|
||||||
fSerialPort.Close();
|
fSerialPort.Close();
|
||||||
}
|
}
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case kMsgDataRead:
|
case kMsgDataRead:
|
||||||
{
|
{
|
||||||
@ -68,13 +111,12 @@ void SerialApp::MessageReceived(BMessage* message)
|
|||||||
ssize_t length;
|
ssize_t length;
|
||||||
message->FindData("data", B_RAW_TYPE, (const void**)&bytes,
|
message->FindData("data", B_RAW_TYPE, (const void**)&bytes,
|
||||||
&length);
|
&length);
|
||||||
if (fLogFile->Write(bytes, length) != length)
|
if (fLogFile->Write(bytes, length) != length) {
|
||||||
{
|
|
||||||
// TODO error handling
|
// TODO error handling
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case kMsgDataWrite:
|
case kMsgDataWrite:
|
||||||
{
|
{
|
||||||
@ -82,11 +124,9 @@ void SerialApp::MessageReceived(BMessage* message)
|
|||||||
ssize_t size;
|
ssize_t size;
|
||||||
|
|
||||||
if (message->FindData("data", B_RAW_TYPE, (const void**)&bytes,
|
if (message->FindData("data", B_RAW_TYPE, (const void**)&bytes,
|
||||||
&size) != B_OK)
|
&size) == B_OK)
|
||||||
break;
|
fSerialPort.Write(bytes, size);
|
||||||
|
return;
|
||||||
fSerialPort.Write(bytes, size);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case kMsgLogfile:
|
case kMsgLogfile:
|
||||||
{
|
{
|
||||||
@ -104,7 +144,7 @@ void SerialApp::MessageReceived(BMessage* message)
|
|||||||
puts(strerror(error));
|
puts(strerror(error));
|
||||||
} else
|
} else
|
||||||
debugger("Invalid BMessage received");
|
debugger("Invalid BMessage received");
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case kMsgSettings:
|
case kMsgSettings:
|
||||||
{
|
{
|
||||||
@ -131,11 +171,134 @@ void SerialApp::MessageReceived(BMessage* message)
|
|||||||
fSerialPort.SetDataRate(rate);
|
fSerialPort.SetDataRate(rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
BApplication::MessageReceived(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle scripting messages
|
||||||
|
if (message->HasSpecifiers()) {
|
||||||
|
BMessage specifier;
|
||||||
|
int32 what;
|
||||||
|
int32 index;
|
||||||
|
const char* property;
|
||||||
|
|
||||||
|
BMessage reply(B_REPLY);
|
||||||
|
BMessage settings(kMsgSettings);
|
||||||
|
bool settingsChanged = false;
|
||||||
|
|
||||||
|
if (message->GetCurrentSpecifier(&index, &specifier, &what, &property)
|
||||||
|
== B_OK) {
|
||||||
|
switch (kScriptingProperties.FindMatch(message, index, &specifier,
|
||||||
|
what, property)) {
|
||||||
|
case 0: // baudrate
|
||||||
|
if (message->what == B_GET_PROPERTY) {
|
||||||
|
reply.AddInt32("result", fSerialPort.DataRate());
|
||||||
|
message->SendReply(&reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (message->what == B_SET_PROPERTY) {
|
||||||
|
int32 rate = message->FindInt32("data");
|
||||||
|
settingsChanged = true;
|
||||||
|
settings.AddInt32("baudrate", rate);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1: // data bits
|
||||||
|
if (message->what == B_GET_PROPERTY) {
|
||||||
|
reply.AddInt32("result", fSerialPort.DataBits() + 7);
|
||||||
|
message->SendReply(&reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (message->what == B_SET_PROPERTY) {
|
||||||
|
int32 bits = message->FindInt32("data");
|
||||||
|
settingsChanged = true;
|
||||||
|
settings.AddInt32("databits", bits - 7);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // stop bits
|
||||||
|
if (message->what == B_GET_PROPERTY) {
|
||||||
|
reply.AddInt32("result", fSerialPort.StopBits() + 1);
|
||||||
|
message->SendReply(&reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (message->what == B_SET_PROPERTY) {
|
||||||
|
int32 bits = message->FindInt32("data");
|
||||||
|
settingsChanged = true;
|
||||||
|
settings.AddInt32("stopbits", bits - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: // parity
|
||||||
|
{
|
||||||
|
static const char* strings[] = {"none", "odd", "even"};
|
||||||
|
if (message->what == B_GET_PROPERTY) {
|
||||||
|
reply.AddString("result",
|
||||||
|
strings[fSerialPort.ParityMode()]);
|
||||||
|
message->SendReply(&reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (message->what == B_SET_PROPERTY) {
|
||||||
|
BString bits = message->FindString("data");
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
if (bits == strings[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 3) {
|
||||||
|
settingsChanged = true;
|
||||||
|
settings.AddInt32("parity", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: // flow control
|
||||||
|
{
|
||||||
|
static const char* strings[] = {"none", "hardware",
|
||||||
|
"software", "both"};
|
||||||
|
if (message->what == B_GET_PROPERTY) {
|
||||||
|
reply.AddString("result",
|
||||||
|
strings[fSerialPort.FlowControl()]);
|
||||||
|
message->SendReply(&reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (message->what == B_SET_PROPERTY) {
|
||||||
|
BString bits = message->FindString("data");
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (bits == strings[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 4) {
|
||||||
|
settingsChanged = true;
|
||||||
|
settings.AddInt32("flowcontrol", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: // port
|
||||||
|
if (message->what == B_GET_PROPERTY) {
|
||||||
|
reply.AddString("port", GetPort());
|
||||||
|
message->SendReply(&reply);
|
||||||
|
} else if (message->what == B_DELETE_PROPERTY
|
||||||
|
|| message->what == B_SET_PROPERTY) {
|
||||||
|
BString path = message->FindString("data");
|
||||||
|
BMessage openMessage(kMsgOpenPort);
|
||||||
|
openMessage.AddString("port name", path);
|
||||||
|
PostMessage(&openMessage);
|
||||||
|
fWindow->PostMessage(&openMessage);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingsChanged) {
|
||||||
|
PostMessage(&settings);
|
||||||
|
fWindow->PostMessage(&settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BApplication::MessageReceived(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -229,3 +392,25 @@ int main(int argc, char** argv)
|
|||||||
SerialApp app;
|
SerialApp app;
|
||||||
app.Run();
|
app.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
SerialApp::GetSupportedSuites(BMessage* message)
|
||||||
|
{
|
||||||
|
message->AddString("suites", "suite/vnd.Haiku-SerialPort");
|
||||||
|
message->AddFlat("messages", &kScriptingProperties);
|
||||||
|
return BApplication::GetSupportedSuites(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BHandler*
|
||||||
|
SerialApp::ResolveSpecifier(BMessage* message, int32 index,
|
||||||
|
BMessage* specifier, int32 what, const char* property)
|
||||||
|
{
|
||||||
|
if (kScriptingProperties.FindMatch(message, index, specifier, what,
|
||||||
|
property) >= 0)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
return BApplication::ResolveSpecifier(message, index, specifier, what,
|
||||||
|
property);
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
|
#include <PropertyInfo.h>
|
||||||
#include <SerialPort.h>
|
#include <SerialPort.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
@ -20,28 +21,33 @@ class SerialWindow;
|
|||||||
class SerialApp: public BApplication
|
class SerialApp: public BApplication
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SerialApp();
|
SerialApp();
|
||||||
~SerialApp();
|
~SerialApp();
|
||||||
void ReadyToRun();
|
void ReadyToRun();
|
||||||
void MessageReceived(BMessage* message);
|
void MessageReceived(BMessage* message);
|
||||||
bool QuitRequested();
|
bool QuitRequested();
|
||||||
|
|
||||||
const BString& GetPort();
|
status_t GetSupportedSuites(BMessage* message);
|
||||||
|
BHandler* ResolveSpecifier(BMessage*, int32, BMessage*, int32,
|
||||||
|
const char*);
|
||||||
|
|
||||||
|
const BString& GetPort();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadSettings();
|
void LoadSettings();
|
||||||
void SaveSettings();
|
void SaveSettings();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BSerialPort fSerialPort;
|
BSerialPort fSerialPort;
|
||||||
sem_id fSerialLock;
|
sem_id fSerialLock;
|
||||||
SerialWindow* fWindow;
|
SerialWindow* fWindow;
|
||||||
BFile* fLogFile;
|
BFile* fLogFile;
|
||||||
BString fPortPath;
|
BString fPortPath;
|
||||||
|
|
||||||
static status_t PollSerial(void*);
|
static status_t PollSerial(void*);
|
||||||
|
|
||||||
static const char* kApplicationSignature;
|
static const BPropertyInfo kScriptingProperties;
|
||||||
|
static const char* kApplicationSignature;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012, Adrien Destugues, pulkomandy@gmail.com
|
* Copyright 2012-2014, Adrien Destugues, pulkomandy@pulkomandy.tk
|
||||||
* Distributed under the terms of the MIT licence.
|
* Distributed under the terms of the MIT licence.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -242,6 +242,7 @@ void SerialWindow::MenusBeginning()
|
|||||||
new BMessage(kMsgOpenPort), 'Z', B_OPTION_KEY);
|
new BMessage(kMsgOpenPort), 'Z', B_OPTION_KEY);
|
||||||
if (!connected)
|
if (!connected)
|
||||||
disconnect->SetEnabled(false);
|
disconnect->SetEnabled(false);
|
||||||
|
disconnect->SetTarget(be_app);
|
||||||
fConnectionMenu->AddItem(disconnect);
|
fConnectionMenu->AddItem(disconnect);
|
||||||
} else {
|
} else {
|
||||||
BMenuItem* noDevices = new BMenuItem("<no serial port available>", NULL);
|
BMenuItem* noDevices = new BMenuItem("<no serial port available>", NULL);
|
||||||
@ -253,16 +254,8 @@ void SerialWindow::MenusBeginning()
|
|||||||
|
|
||||||
void SerialWindow::MessageReceived(BMessage* message)
|
void SerialWindow::MessageReceived(BMessage* message)
|
||||||
{
|
{
|
||||||
switch(message->what)
|
switch (message->what)
|
||||||
{
|
{
|
||||||
case kMsgOpenPort:
|
|
||||||
{
|
|
||||||
BMenuItem* disconnectMenu;
|
|
||||||
if (message->FindPointer("source", (void**)&disconnectMenu) == B_OK)
|
|
||||||
disconnectMenu->SetMarked(false);
|
|
||||||
be_app->PostMessage(new BMessage(*message));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kMsgDataRead:
|
case kMsgDataRead:
|
||||||
{
|
{
|
||||||
const char* bytes;
|
const char* bytes;
|
||||||
@ -270,7 +263,7 @@ void SerialWindow::MessageReceived(BMessage* message)
|
|||||||
if (message->FindData("data", B_RAW_TYPE, (const void**)&bytes,
|
if (message->FindData("data", B_RAW_TYPE, (const void**)&bytes,
|
||||||
&length) == B_OK)
|
&length) == B_OK)
|
||||||
fTermView->PushBytes(bytes, length);
|
fTermView->PushBytes(bytes, length);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case kMsgLogfile:
|
case kMsgLogfile:
|
||||||
{
|
{
|
||||||
@ -281,7 +274,7 @@ void SerialWindow::MessageReceived(BMessage* message)
|
|||||||
fLogFilePanel->SetMessage(message);
|
fLogFilePanel->SetMessage(message);
|
||||||
}
|
}
|
||||||
fLogFilePanel->Show();
|
fLogFilePanel->Show();
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case kMsgSettings:
|
case kMsgSettings:
|
||||||
{
|
{
|
||||||
@ -348,9 +341,9 @@ void SerialWindow::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
BWindow::MessageReceived(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BWindow::MessageReceived(message);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012, Adrien Destugues, pulkomandy@gmail.com
|
* Copyright 2012-2014, Adrien Destugues, pulkomandy@pulkomandy.tk
|
||||||
* Distributed under the terms of the MIT licence.
|
* Distributed under the terms of the MIT licence.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -15,24 +15,25 @@ class TermView;
|
|||||||
class SerialWindow: public BWindow
|
class SerialWindow: public BWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SerialWindow();
|
SerialWindow();
|
||||||
~SerialWindow();
|
~SerialWindow();
|
||||||
|
|
||||||
|
void MenusBeginning();
|
||||||
|
void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
void MenusBeginning();
|
|
||||||
void MessageReceived(BMessage* message);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TermView* fTermView;
|
TermView* fTermView;
|
||||||
|
|
||||||
BMenu* fConnectionMenu;
|
BMenu* fConnectionMenu;
|
||||||
BMenu* fDatabitsMenu;
|
BMenu* fDatabitsMenu;
|
||||||
BMenu* fStopbitsMenu;
|
BMenu* fStopbitsMenu;
|
||||||
BMenu* fParityMenu;
|
BMenu* fParityMenu;
|
||||||
BMenu* fFlowcontrolMenu;
|
BMenu* fFlowcontrolMenu;
|
||||||
BMenu* fBaudrateMenu;
|
BMenu* fBaudrateMenu;
|
||||||
BFilePanel* fLogFilePanel;
|
BFilePanel* fLogFilePanel;
|
||||||
|
|
||||||
static const int kBaudrates[];
|
static const int kBaudrates[];
|
||||||
static const int kBaudrateConstants[];
|
static const int kBaudrateConstants[];
|
||||||
static const char* kWindowTitle;
|
static const char* kWindowTitle;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user