Problem access to GPIO rasbery pi 3 with android things - gpio

I want to turn on A LED with android things and raspberry Pi 3. I did it as instructed in https://developer.android.com/things/sdk/pio/gpio. And I am using last android things version (1.0.15).
any comments why I get a such error?
2009-01-01 03:30:07.762 667-667/com.inflashpay.inflash
E/Request Permission: List of available ports: [BCM2] 2009-01-01
03:30:07.774 667-667/com.inflashpay.inflash E/Request Permission:
Unable to access GPIO
com.google.android.things.pio.PioException: android.os.ServiceSpecificException: BCM2 failed to apply the required
pin mux: No such file or directory (code 2)
added:
private static final String LED = "BCM2";
private Handler mHandler = new Handler();
private Gpio mLedGpio;
PeripheralManager service = PeripheralManager.getInstance();
Log.i(TAG, "Available GPIO: " + service.getGpioList());
try {
mLedGpio = service.openGpio(LED);
mLedGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
Log.i(TAG, "Start blinking LED GPIO pin");
// Post a Runnable that continuously switch the state of the GPIO, blinking the
// corresponding LED
mHandler.post(mBlinkRunnable);
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}

The code sounds good, but the problem is probably the GPIO name.
Check out the pinout diagram of the Raspberry Pi
You can see that BCM2 is not available (although BCM21 is)
You can see another example that uses the pins on the Rainbow HAT on this sample. That one I have run and verified that works. Feel free to compare the project with yours or clone the repo and try that code.

I modified CONFIG file because I needed to use a monitor needed to change resolution there, and when I restored it to default problem solved.

Related

Main Camera Referenced script is missing

I know, there is always a lot of questions about this error BUT I didn't succeed to fix it with the previous answers...
So, please, let me explain.
I'm working with the Hololens tech. Recently, I have updated from HoloToolKit to MRTK V2 (new SDK provided by Microsoft and the community). My app worked with HoloToolKit, Unity and 2017.4. I updated for MRTKv2 and 2019.2 (recommended).
I have some scripts that use the camera position. In my previous app, Camera was BiCamera (GameObject), child of Basic (GameObject). And my BiCamera was tagged as MainCamera. Right now, my camera was Main Camera (with a space between the 2 words), tagged MainCamera, child of MixedRealityPlayspace. This camera is provided by the MRTKv2. I can't change the settings.
So, when I'm in a Play mode I have this message in yellow :
The referenced script on this Behaviour (Game Object 'Main Camera') is missing!
And when I move my Main Camera in order to simulate a walk of the user (Hololens = augmented reality), I have this message in red :
NullReferenceException: Object reference not set to an instance of an object
TextSpeedUI.Update () (at Assets/Scripts/TextSpeedUI.cs:23)
I think the second message is linked to the first... My script TextSpeedUI needs the camera.transform to calculate walking speed (in fact not directly, he finds the public variable from another GameObject, but this GameObject requires Camera.transform).
An other option is linked with the GameObject Main Camera provided by MRTK because when I select this GameObject I have a missing script. A message says that I have to fix compile errors... But perhaps it's a consequence not the origin... I'm lost.
TextSpeedUI.cs 23
if (sd.isActiveAndEnabled && sd.Steps.Count > 4)
{
xzSpeed = (sd.Steps[sd.Steps.Count - 1].localMinPosition - sd.Steps[sd.Steps.Count - 4].localMinPosition) / ((sd.Steps[sd.Steps.Count - 1].t - sd.Steps[sd.Steps.Count - 4].t));
txt.text = (xzSpeed.magnitude * 3.6).ToString("0.##"); // speed in km/h
}
sd comes from public StepDetector sd; which is at the beginning of my script TextSpeedUI.cs
And my script StepDetector.cs calls public DataManager dm;
In my DataManager.cs script, I call at the beginning :
public Camera Cam { get; private set; }
And in void Start :
Cam = Camera.main;
Thanks a lot
I've solved by myself (just remove the component). It seems that it doesn't have consequence on my scene...

How to Self-Lock a Javacard Applet

My question is whether it is possible to lock an applet from within the code of the applet itself as a countermeasure to detected manipulations from within the code.
The obvious choice is to use GPSystem.lockCard(); and it works, however I wonder if it is possible to only lock the applet. Also I can lock the applet itself from an authenticated session of the associated security domain. But is it possible from the applet code itself. It seems, given the GPSystem.setCardContentState(); method used with GPSystem.APPLICATION_LOCKED, so I also tested that but it does not work.
Rereading the description of the GP Card specification 2.2 PDF:
The OPEN shall reject any transition request from the Life Cycle State LOCKED;
In my Eclipse, the JavaDoc says:
The OPEN shall reject any transition request to the Life Cycle State LOCKED
What's going on here?
It's interesting to see how this mechanism evolved from GlobalPlatform Card specification 2.1.1 to 2.2.1 (still the same in 2.3):
In GP 2.1.1, only the card issuer (off-card entity) or the OPEN (as a result of "exceptions") is allowed to initiate locking of an application:
The Card Issuer has a mechanism to disable the continued execution status of an on-card Application. This mechanism may be invoked from within the OPEN based on exceptions handled by the OPEN or from the use of externally invoked commands. The Card Issuer is the only entity that may initiate the locking of an Application.
The method GPSystem.setCardContentState() is clearly defined to allow only state changes to application specific life-cycle states (values between 0x07 and 0x7F with the lowest 3 bits set). Since the constant for APPLICATION_LOCKED in later specifications is 0x80 setting this state is not allowed. This is also made clear in the notes to this method:
The OPEN shall reject any transition request to the Life Cycle States INSTALLED or LOCKED.
Consequently, trying to set the application state to locked from within the application itself must fail on a card implementing GP 2.1.1.
UPDATE (2016-05-20): I tested this on a few NXP JCOP cards (that are claimed to comply to GP 2.1.1) and setting values that have the upper bit set or any of the lower 3 bits cleared indeed fails.
This changed in GP 2.2. Now, an application is allowed to lock itself:
The card has a mechanism to disable and subsequently re-enable the continued execution status of an on-card
Application. This mechanism may be invoked from within the OPEN based on exceptions handled by the OPEN or
from the use of externally invoked commands. An Application with Global Lock privilege, the Application itself or
a directly or indirectly associated Security Domain are the only entities that may initiate the locking of an
Application.
The GP Card specification does not require an application to hold any specific permission to lock itself.
Unfortunately, the API specification for the method GPSystem.setCardContentState() is still not quite clear. First, the description of the method still states that only values between 0x07 and 0x7F with the lowest 3 bits set must be allowed:
This method sets the Application specific Life Cycle State of the current applet context. Application specific Life Cycle States range from 0x07 to 0x7F as long as the 3 low order bits are set.
Second, there are deviating notes in the API documentation thats part of appendix A of the GP Card specification 2.2 document and the JavaDoc in the API export files. While the notes in the specification were changed to:
The OPEN shall reject any transition request to the Life Cycle State INSTALLED;
The OPEN shall reject any transition request from the Life Cycle State LOCKED;
The notes in the API export files (GPSystem.java and JavaDoc) remained the same as in GP 2.1.1.
Consequently, if this method was implemented according to the specification, it should still reject setting the application life-cycle state to APPLICATION_LOCKED.
UPDATE (2016-05-20): I tested this on a NXP J3D081 (JCOP v2.4.2 R2) card (that is claimed to comply to GP 2.2). Setting values that have the upper bit set or any of the lower 3 bits cleared, unfortunately, fails.
However, there is also the method GPRegistryEntry.setState(). The documentation of this method states that:
A transition request to Life Cycle state other than APPLICATION_LOCKED and APPLICATION_UNLOCKED shall be accepted only if the invoking Application corresponds to this GPRegistryEntry;
An Application shall be able to lock and shall not be able to unlock itself;
Thus, it would be interesting to see if the following worked on the same card where using setCardContentState() failed:
GPSystem.getRegistryEntry(null).setState(GPSystem.APPLICATION_LOCKED);
UPDATE (2016-05-20): I tested this on a NXP J3D081 (JCOP v2.4.2 R2) card (that is claimed to comply to GP 2.2). Unfortunately, this fails as well. Btw. it does not seem to make a difference if null or JCSystem.getAID() is used as parameter for getRegistryEntry().
UPDATE (2016-06-14): According to Paul Bastian, an NXP representative has confirmed that applications cannot set themselves to locked state on JCOP v2.4.x cards.
UPDATE (2016-06-06): I tested this on a Infineon SLE97CNFX card (that is claimed to comply to GP 2.2.1) and it worked. I could successfully set the state to locked by using APPLICATION_LOCKED (0x80). The state is then set to previous_state | 0x80. Trying to set other state values that have the upper bit set (e.g. 0x8F) does not work (just as I expected).
In GP 2.2.1, the documentation of the method GPSystem.setCardContentState() was changed (again). The change note clearly indicates that the method was updated to now allow an application to lock itself (export file version 1.5. maps to GP 2.2.1):
export file version 1.5: this method now allows the application associated with the current applet context to lock itself.
The method definition was changed to:
This method allows the application associated with the current applet context to change its state to an application specific life cycle state or to lock itself. An application cannot unlock itself using this method.
The value range for the state parameter passed to the method now explicitly includes the value of APPLICATION_LOCKED:
bState - an application specific life cycle state (0x07 to 0x7F with 3 low order bits set), or APPLICATION_LOCKED (0x80).
Consequently, cards implementing GP 2.2.1 or higher should eventually allow applications to change their own life-cycle state to locked using the method GPSystem.setCardContentState().
UPDATE (2016-06-06): I tested this on a Infineon SLE97CNFX card (that is claimed to comply to GP 2.2.1 (or is it 2.3?)) and it worked. I could successfully set the state to locked by using APPLICATION_LOCKED (0x80). The state is then set to previous_state | 0x80. Trying to set other state values that have the upper bit set (e.g. 0x8F) does not work (just as I expected).
An alternative solution
What you could do to overcome your problem without being able to set the application life-cycle to state APPLICATION_LOCKED, is to use application-specific life-cycle states:
public class LockableApplet extends Applet {
[... applet installation / instantiation code ...]
private static final byte APPLICATION_STATE_UNLOCKED = (byte)0x07;
private static final byte APPLICATION_STATE_LOCKED = (byte)0x7F;
public boolean select() {
if (GPSystem.getCardContentState() == APPLICATION_STATE_LOCKED) {
return false;
}
return true;
}
public void process(APDU apdu) {
if (selectingApplet()) {
return;
}
if (GPSystem.getCardContentState() == APPLICATION_STATE_LOCKED) {
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
}
[... applet logic code ...]
}
}
Upon detecting a problem that should cause your application to be locked, you could lock the applet with the following call:
GPSystem.setCardContentState(APPLICATION_STATE_LOCKED);
You could later unlock the application again using a SET STATUS command through the security domain.
(Buyer beware: It seems this way simply does not work -- see comments)
(In context of GlobalPlatform Card Specification 2.2.1)
You must obey the Application Life Cycle State rules depicted in figure 5-2 (the arrow marked '5' applies here).
The correct way should be:
GPSystem.setCardContentState((byte)(GPSystem.getCardContentState() | GPSystem.APPLICATION_LOCKED));
or
GPSystem.getRegistryEntry(JCSystem.getAID()).setState((byte)(GPSystem.getCardCo‌​ntentState() | GPSystem.APPLICATION_LOCKED))
The 0x80 life cycle state is invalid for an application. See table 11-4 ( at least the b1 and b2 bits must be set, the b3 bit probably as well).
EDIT>
(I confess to write this answer based solely on the remembrance of fact that OPEN keeps the original state from which the entity was locked)
I am quite curious about this so I did some tests using the following applet (excerpt):
public void process(APDU apdu) {
byte[] buffer = apdu.getBuffer();
if(selectingApplet()) {
return;
}
short claIns = Util.getShort(buffer, ISO7816.OFFSET_CLA);
switch(claIns) {
case (short) 0x8007:
buffer[0]=GPSystem.getCardContentState();
if(buffer[0]==buffer[ISO7816.OFFSET_P1]) {
if(GPSystem.setCardContentState(buffer[ISO7816.OFFSET_P2])) {
buffer[1]=0x01;
} else {
buffer[1]=0x00;
}
} else {
buffer[1]=(byte)0xFF;
}
buffer[2]=GPSystem.getCardContentState();
apdu.setOutgoingAndSend((short)0, (short)3);
return;
default: {
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
return;
}
}
}
And the following APDUs:
8007070F03 // To test transition into Application Specific State
80070F8F03 // To test my theory
80070F8003 // To test the GPSystem.APPLICATION_LOCKED constant directly
The results for my set of cards (Gemalto, Morpho, JCOP -- unfortunately all of them are GP 2.1.1) are in line with Michael Roland's great answer and GP specs -- the application's attempt to block itself is refused.
Received response APDUs for all GP 2.1.1 cards:
8007070F03 -> 07010F9000 // Succeeded in transition from `07` to `0F`
80070F8F03 -> 0F000F9000 // Failed transition from `0F` to `8F`
80070F8003 -> 0F000F9000 // Failed transition from `0F` to `80`
Just a note: This tool is quite useful to determine the implemented GP version as it parses the Card Recognition Data.
Yes. It is common and intended operation of a GlobalPlatform application. You must install your application with the right privilege (gp -install -privs CardLock) and the code to do it is:
GPSystem.setCardContentState(GPSystem.APPLICATION_LOCKED);
You can later unlock the application with
gp -unlock-applet <aid>
There is no compliance to GP core spec per se. A product is GP compliant to a GP configuration. GP configuration are not free of charge. JCOP 2.4.x products are compliant to GP 2.2.x 'Mapping Guidelines of Existing GP 2.1.1 Implementation on v2.2.1' configuration. As the name suggests, this configuration is for backward compatibility mapping. Basically JCOP 2.4.x products are GP 2.1.1 compliant products only (with a couple features from GP 2.2.x). Global Lock privilege is optional for applets.
Yes, it is quite simple: use a private static boolean flag and check it in the beginning of the process(APDU apdu) method:
public class MiniApplet extends Applet {
public static void install(byte[] bArray, short bOffset, byte bLength) {
new MiniApplet();
}
protected MiniApplet() {
register();
}
private static final short SW_APPLET_IS_LOCKED = (short) 0x9199; //any error SW
private static boolean appletLocked = false; //static -> faster access, this flag is checked each call! "private" modifier is VERY important!
public void process(APDU apdu) {
if (selectingApplet()) {
return; //it is a good practice not to throw any exceptions on SELECT command
}
if (appletLocked) {
ISOException.throwIt(SW_APPLET_IS_LOCKED);
}
if (attackDetected()) { //implement your attack detection
appletLocked = true;
}
}
}

Component unable to allocate device that is not Executable Device

I am using Redhawk 1.9. I create a Redhawk Device, Component, Node, and Waveform with default settings. I use C++ implementation on all the above. The problem is that the device can't be allocated since it is not an executable device. In the implementation tab in the code section the "type" variable is set to "Executable" (default value). If this is incorrect then what should it be?
Note: When I make an Device derived from executable device then the problem goes away.
I was able to reproduce the problem with dummy device and component as shown below:
I update the Component so that it will use the device.
<usesdevice id="dummy_device_2" type="usesdevice">
<propertyref refid="DCE:cdc5ee18-7ceb-4ae6-bf4c-31f983179b4d" value="dummy_device_kind_1"/>
</usesdevice>
I update the device properties:
<simple id="DCE:cdc5ee18-7ceb-4ae6-bf4c-31f983179b4d" mode="readonly" name="device_kind" type="string">
<description>This specifies the device kind</description>
<value>dummy_device_kind_1</value>
<kind kindtype="configure"/>
<kind kindtype="allocation"/>
<action type="eq"/>
</simple>
I add the Dummy device created here into the dummy node created here.
I add the Dummy Component to the Dummy Waveform.
I launched the Dummy node that only contains the dummy device
I launched the Dummy waveform that only contains the above dummy device.
I get the following error message:
Failed to create application:
DeviceOnlyTestWaveform_343_114533234 The
following CORBA exception occurred: InvalidCapacity while creating the
application IDL:CF/ApplicationFactory/CreateApplicationError:1.0*
The Domain Manager (run with Trace logging) shows the following:
DEBUG:ApplicationFactory_impl - Trying to find the device
TRACE:ApplicationFactory_impl - Searching for a place to deploy component amongst 1 devices
TRACE:ApplicationFactory_impl - Checking Device DummyNode:DeviceOnlyTesTDevice_1
TRACE:ApplicationFactory_impl - Device DummyNode:DeviceOnlyTesTDevice_1 is loadable
TRACE:ApplicationFactory_impl - Device DummyNode:DeviceOnlyTesTDevice_1 is not loadable
TRACE:ApplicationFactory_impl - Done checking all the devices
DEBUG:ApplicationFactory_impl - Device Allocation Failed.. need to clean up
In ApplicationFactory_impl the code appear to show that the allocation fails since the device is not derived from Executable Device. The code section has "type" to Executable (default setting). If this is not correct then what should it be?
// Check that the device meet's the needs of this component
// - Validate the type of device meets the requirements in the 'code' section of the implementation
//
LOG_TRACE(ApplicationFactory_impl, "Checking Device " << deviceNodeIter->identifier);
if (deviceNodeIter->device->usageState() == CF::Device::BUSY)
{
LOG_TRACE(ApplicationFactory_impl, "Ignoring Device " <<deviceNodeIter->label << " is BUSY");
continue;
}
if ((implementation->getCodeType() == CF::LoadableDevice::EXECUTABLE) ||
(implementation->getCodeType() == CF::LoadableDevice::SHARED_LIBRARY)) {
// Does this device provide LoadableDevice?
LOG_TRACE(ApplicationFactory_impl, "Device " << deviceNodeIter->identifier << " is loadable");
CF::LoadableDevice_var loaddev;
loaddev = ossie::corba::_narrowSafe<CF::LoadableDevice> (deviceNodeIter->device);
if(CORBA::is_nil(loaddev)) {
LOG_TRACE(ApplicationFactory_impl, "Device " << deviceNodeIter->identifier << " is not loadable");
continue;
}
if (implementation->getEntryPoint().size() != 0) {
// Does this device provide ExecutableDevice?
LOG_TRACE(ApplicationFactory_impl, "Device " << deviceNodeIter->identifier << " is executable");
CF::ExecutableDevice_var execdev;
execdev = ossie::corba::_narrowSafe<CF::ExecutableDevice> (deviceNodeIter->device);
if(CORBA::is_nil(execdev)) {
LOG_INFO(ApplicationFactory_impl, "Device " << deviceNodeIter->identifier << " is not executable");
continue;
}
}
}
Although your device is capable of satisfying the usesdevice allocation, without a GPP or other ExecutableDevice, there is no place to run your component. There are two ways that allocation is performed when launching components:
Satisfying usesdevice relationships
Deciding on which device to deploy the executable
Each implementation in the component's SPD has a list of dependencies that must be satisfied to run the entry point. Typically, for a C++ component, this will include the OS and processor type. Additional requirements can be defined based on the processing requirements of the component, such as memory or load average; these must be allocation properties known to the target device, just like with usesdevice. There is also an implicit requirement that the device selected for deployment should support the ExecutableDevice interface (there is slightly more nuance to it, but that's by far the most common case).
When launching a waveform, the ApplicationFactory tries to allocate all required devices and select an implementation for each component in sequence. Each possible implementation is checked against all of the devices in the domain to see if there is a device that meets its dependencies. If so, the entry point for that implementation will be loaded onto the device and executed, and the ApplicationFactory moves on to the next component. If no suitable device can be found, it throws a CreateApplicationError, as you are seeing.
For most cases, you can use the GPP device included with REDHAWK to support the execution of your components. You would usually only write your own ExecutableDevice if you have a specific type of hardware that does not work with GPP, like an FPGA. If you have installed from RPM, there should be a node tailored to your local system (e.g., processor type, Java and Python versions) in your $SDRROOT/dev/nodes directory. Otherwise you can create it yourself with the 'nodeconfig.py' script included with the GPP project; see the Ubuntu installation guide for an example (admittedly, somewhat buried in the REDHAWK Manual, Appendix E, Section 5).
I believe the problem is that you don't have a GPP in the node with your Dummy Device. Because your original Device was not Executable, it was unable to execute the Component's code, which is what the GPP would do for you.
To add the GPP in the IDE, simply open up the DeviceManager.dcd.xml file of your Node, navigate to the Devices tab, and click the Add button. If everything is installed correctly, you should be able to select the GPP, then click Finish. Finally, save the Node and drag it to Target SDR and try launching it with nodeBooter again.
Also, the type "Executable" in the *.spd.xml file isn't specific to Devices. If you look at the implementation section for a Component, you'll notice there is a Type drop down under the Code section as well. The reason for this is because it isn't describing the type of Device/Component, but how the output of the build process should be interpreted.

Java Thread Safety v Displaying a Dialog from separate Thread

Hi noticed some code in our application when I first started Java programming. I had noticed it created a dialog from a separate thread, but never batted an eye lid as it 'seemed to work'. I then wrapped this method up through my code to display dialogs.
This is as follows:
public class DialogModalVisibleThread
extends Thread {
private JDialog jDialog;
public DialogModalVisibleThread(JDialog dialog, String dialogName) {
this.setName("Set " + dialogName + " Visable");
jDialog = dialog;
}
#Override
public void run() {
jDialog.setVisible(true);
jDialog.requestFocus();
}
}
Usage:
WarnUserDifferenceDialog dialog = new WarnUserDifferenceDialog( _tableDifferenceCache.size() );
DialogModalVisibleThread dmvt = new DialogModalVisibleThread( dialog, "Warn User About Report Diffs");
dmvt.start();
Now, as far as I am now aware, you should never create or modify swing components from a separate thread. All updates must be carried out on the Event Dispatch Thread. Surely this applies to the above code?
EDT on WikiPedia
However, the above code has worked.
But lately, there have been countless repaint issues. For example, click on a JButton which then calls DialogModalVisibleThread to display a dialog. It caused buttons alongside the clicked button not to redraw properly.
The repaint problem is more frequent on my machine and not the other developers machine. The other developer has a laptop with his desktop extended onto a 21" monitor - the monitor being his main display. He is running Windows 7 with Java version 1.6.0_27.
I am running on a laptop with Windows 7 and Java version 1.6.0_24. I have 2 additional monitors with my desktop extended onto both.
In the meantime I am going to upgrade to Java 1.6 update 27.
I wondered if the above code could cause repaint problems or are there any other people out there with related paint issues?
Are there any easy ways to diagnose these problems?
Thanks
So, you're breaking a rule, having problems, and wondering if these problems could be cause by the fact that you broke the rule. The answer is Yes. Respect the rules!
To detect the violations, you might be interested by the following page: http://weblogs.java.net/blog/2006/02/16/debugging-swing-final-summary
The easiest way to check if your problems are being caused by breaking the rules is to fix them (You should fix them anyway :-)
Just use SwingWorker.invokeLater() from the thread you want to update to UI from to easily adhere to Swing's contract. Something like this should do the trick:
#Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
jDialog.setVisible(true);
jDialog.requestFocus();
}
});
}
EDIT: You should make the 'jDialog' variable final for this to work.

SerialPort in mono in linux not responding to DataReceived event

I am writing an app that uses the serial port exposed by the SerialPort class in mono. What I have written so far works perfect in windows, however in linux the DataReceived event handler is never entered, so I cannot receive any data form my device. I have declared the event handler as follows:
comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
Basically I am exploring good cross-platform options and this is a deal-breaker. Any advise on how to fix this or what is going on?
Edit-
I should also point out that I have tested the serial port and device on linux with other applications and all appears to be working.
Maybe it has changed lastly, but as far as I know, events are not currently implemented in Mono's serial port. You have to make another thread in any flavour to read data from serial port, which happens in blocking manner. Try it and tell if it worked.
On Antanas Veiverys blog you can find two possible ways to solve it.
(2012) By adjusting the mono source code.
http://antanas.veiverys.com/enabling-serialport-datareceived-event-in-mono/
(2013) By not touching the mono source but solving the issue in a derived class.
http://antanas.veiverys.com/mono-serialport-datareceived-event-workaround-using-a-derived-class/
(2014)
However, I encourage you to read Ben Voigts blog post where he ignores using the DataReceivedEvent and instead used the BaseStream async BeginRead/EndRead functions to read data from the serial port.
http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport#comment-840
Implementing and using the given code sample works on both Windows/Unix, so I have tested. And it is more elegant than using the blocking Read() function in a threaded fashion.
mono does not support Event for serialport.
It is shown on mono's website
I have the same problem with SerialPort.DataReceived. Konrad's advice.
using System.IO.Ports;
using System.Threading;
namespace Serial2
{
class MainClass
{
public static void Main(string[] args)
{
Thread writeThread = new Thread(new ThreadStart(WriteThread));
Thread readThread = new Thread(new ThreadStart(ReadThread));
readThread.Start();
Thread.Sleep(200); // TODO: Ugly.
writeThread.Start();
Console.ReadLine();
}
private static void WriteThread()
{ // get port names with dmesg | grep -i tty
SerialPort sp2 = new SerialPort("/dev/ttyS5", 115200, Parity.None, 8, StopBits.One);
sp2.Open();
if(sp2.IsOpen)
Console.WriteLine("WriteThread(), sp2 is open.");
else
Console.WriteLine("WriteThread(), sp2 is open.");
sp2.Write(" This string has been sent over an serial 0-modem cable.\n"); // \n Needed (buffering?).
sp2.Close();
}
private static void ReadThread()
{
SerialPort sp = new SerialPort("/dev/ttyS4", 115200, Parity.None, 8, StopBits.One);
sp.Open();
if(sp.IsOpen)
Console.WriteLine("ReadThread(), sp Opened.");
else
Console.WriteLine("ReadThread(), sp is not open.");
while(true)
{
Thread.Sleep(200);
if(sp.BytesToRead > 0)
{
Console.WriteLine(sp.ReadLine());
}
}
}
}
}

Resources