Skip to content

Commit 122d3df

Browse files
committed
ATRONIX: including serial port related files taken from Atronix's branch
1 parent 3761b7d commit 122d3df

File tree

3 files changed

+912
-0
lines changed

3 files changed

+912
-0
lines changed

src/core/p-serial.c

+243
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
/***********************************************************************
2+
**
3+
** REBOL [R3] Language Interpreter and Run-time Environment
4+
**
5+
** Copyright 2013 REBOL Technologies
6+
** REBOL is a trademark of REBOL Technologies
7+
**
8+
** Licensed under the Apache License, Version 2.0 (the "License");
9+
** you may not use this file except in compliance with the License.
10+
** You may obtain a copy of the License at
11+
**
12+
** http://www.apache.org/licenses/LICENSE-2.0
13+
**
14+
** Unless required by applicable law or agreed to in writing, software
15+
** distributed under the License is distributed on an "AS IS" BASIS,
16+
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
** See the License for the specific language governing permissions and
18+
** limitations under the License.
19+
**
20+
************************************************************************
21+
**
22+
** Module: p-serial.c
23+
** Summary: serial port interface
24+
** Section: ports
25+
** Author: Carl Sassenrath
26+
** Notes:
27+
**
28+
***********************************************************************/
29+
30+
#include "sys-core.h"
31+
#include "reb-net.h"
32+
#include "reb-evtypes.h"
33+
34+
#define MAX_SERIAL_DEV_PATH 128
35+
36+
/***********************************************************************
37+
**
38+
*/ static int Serial_Actor(REBVAL *ds, REBSER *port, REBCNT action)
39+
/*
40+
***********************************************************************/
41+
{
42+
REBREQ *req; // IO request
43+
REBVAL *spec; // port spec
44+
REBVAL *arg; // action argument value
45+
REBVAL *val; // e.g. port number value
46+
REBINT result; // IO result
47+
REBCNT refs; // refinement argument flags
48+
REBCNT len; // generic length
49+
REBSER *ser; // simplifier
50+
REBVAL *path;
51+
52+
Validate_Port(port, action);
53+
54+
*D_RET = *D_ARG(1);
55+
56+
// Validate PORT fields:
57+
spec = OFV(port, STD_PORT_SPEC);
58+
if (!IS_OBJECT(spec)) Trap0(RE_INVALID_PORT);
59+
path = Obj_Value(spec, STD_PORT_SPEC_HEAD_REF);
60+
if (!path) Trap1(RE_INVALID_SPEC, spec);
61+
62+
//if (!IS_FILE(path)) Trap1(RE_INVALID_SPEC, path);
63+
64+
req = Use_Port_State(port, RDI_SERIAL, sizeof(*req));
65+
66+
// Actions for an unopened serial port:
67+
if (!IS_OPEN(req)) {
68+
69+
switch (action) {
70+
71+
case A_OPEN:
72+
arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_PATH); //Should Obj_Value really return a char* ?
73+
if (! (IS_FILE(arg) || IS_STRING(arg) || IS_BINARY(arg))) {
74+
Trap1(RE_INVALID_PORT_ARG, arg);
75+
}
76+
req->serial.path = MAKE_STR(MAX_SERIAL_DEV_PATH);
77+
TO_OS_STR(req->serial.path, (char *) VAL_DATA(arg), MAX_SERIAL_DEV_PATH);
78+
arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_SPEED);
79+
if (! IS_INTEGER(arg)) {
80+
Trap1(RE_INVALID_PORT_ARG, arg);
81+
}
82+
req->serial.baud = VAL_INT32(arg);
83+
//Secure_Port(SYM_SERIAL, ???, path, ser);
84+
arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_DATA_SIZE);
85+
if (!IS_INTEGER(arg)
86+
|| VAL_INT64(arg) < 5
87+
|| VAL_INT64(arg) > 8) {
88+
Trap1(RE_INVALID_PORT_ARG, arg);
89+
}
90+
req->serial.data_bits = VAL_INT32(arg);
91+
92+
arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_STOP_BITS);
93+
if (!IS_INTEGER(arg)
94+
|| VAL_INT64(arg) < 1
95+
|| VAL_INT64(arg) > 2) {
96+
Trap1(RE_INVALID_PORT_ARG, arg);
97+
}
98+
req->serial.stop_bits = VAL_INT32(arg);
99+
100+
arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_PARITY);
101+
if (IS_NONE(arg)) {
102+
req->serial.parity = SERIAL_PARITY_NONE;
103+
} else {
104+
if (!IS_WORD(arg)) {
105+
Trap1(RE_INVALID_PORT_ARG, arg);
106+
}
107+
switch (VAL_WORD_CANON(arg)) {
108+
case SYM_ODD:
109+
req->serial.parity = SERIAL_PARITY_ODD;
110+
break;
111+
case SYM_EVEN:
112+
req->serial.parity = SERIAL_PARITY_EVEN;
113+
break;
114+
default:
115+
Trap1(RE_INVALID_PORT_ARG, arg);
116+
}
117+
}
118+
119+
arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_FLOW_CONTROL);
120+
if (IS_NONE(arg)) {
121+
req->serial.flow_control = SERIAL_FLOW_CONTROL_NONE;
122+
} else {
123+
if (!IS_WORD(arg)) {
124+
Trap1(RE_INVALID_PORT_ARG, arg);
125+
}
126+
switch (VAL_WORD_CANON(arg)) {
127+
case SYM_HARDWARE:
128+
req->serial.flow_control = SERIAL_FLOW_CONTROL_HARDWARE;
129+
break;
130+
case SYM_SOFTWARE:
131+
req->serial.flow_control = SERIAL_FLOW_CONTROL_SOFTWARE;
132+
break;
133+
default:
134+
Trap1(RE_INVALID_PORT_ARG, arg);
135+
}
136+
}
137+
138+
if (OS_DO_DEVICE(req, RDC_OPEN)) Trap_Port(RE_CANNOT_OPEN, port, -12);
139+
SET_OPEN(req);
140+
return R_RET;
141+
142+
case A_CLOSE:
143+
return R_RET;
144+
145+
case A_OPENQ:
146+
return R_FALSE;
147+
148+
default:
149+
Trap_Port(RE_NOT_OPEN, port, -12);
150+
}
151+
}
152+
153+
// Actions for an open socket:
154+
switch (action) {
155+
156+
case A_READ:
157+
refs = Find_Refines(ds, ALL_READ_REFS);
158+
159+
// Setup the read buffer (allocate a buffer if needed):
160+
arg = OFV(port, STD_PORT_DATA);
161+
if (!IS_STRING(arg) && !IS_BINARY(arg)) {
162+
Set_Binary(arg, Make_Binary(32000));
163+
}
164+
ser = VAL_SERIES(arg);
165+
req->length = SERIES_AVAIL(ser); // space available
166+
if (req->length < 32000/2) Extend_Series(ser, 32000);
167+
req->length = SERIES_AVAIL(ser);
168+
req->data = STR_TAIL(ser); // write at tail
169+
//if (SERIES_TAIL(ser) == 0)
170+
req->actual = 0; // Actual for THIS read, not for total.
171+
#ifdef DEBUG_SERIAL
172+
printf("(max read length %d)", req->length);
173+
#endif
174+
result = OS_DO_DEVICE(req, RDC_READ); // recv can happen immediately
175+
if (result < 0) Trap_Port(RE_READ_ERROR, port, req->error);
176+
#ifdef DEBUG_SERIAL
177+
for (len = 0; len < req->actual; len++) {
178+
if (len % 16 == 0) printf("\n");
179+
printf("%02x ", req->data[len]);
180+
}
181+
printf("\n");
182+
#endif
183+
*D_RET = *arg;
184+
return R_RET;
185+
186+
case A_WRITE:
187+
refs = Find_Refines(ds, ALL_WRITE_REFS);
188+
189+
// Determine length. Clip /PART to size of string if needed.
190+
spec = D_ARG(2);
191+
len = VAL_LEN(spec);
192+
if (refs & AM_WRITE_PART) {
193+
REBCNT n = Int32s(D_ARG(ARG_WRITE_LENGTH), 0);
194+
if (n <= len) len = n;
195+
}
196+
197+
// Setup the write:
198+
*OFV(port, STD_PORT_DATA) = *spec; // keep it GC safe
199+
req->length = len;
200+
req->data = VAL_BIN_DATA(spec);
201+
req->actual = 0;
202+
203+
//Print("(write length %d)", len);
204+
result = OS_DO_DEVICE(req, RDC_WRITE); // send can happen immediately
205+
if (result < 0) Trap_Port(RE_WRITE_ERROR, port, req->error);
206+
break;
207+
case A_UPDATE:
208+
// Update the port object after a READ or WRITE operation.
209+
// This is normally called by the WAKE-UP function.
210+
arg = OFV(port, STD_PORT_DATA);
211+
if (req->command == RDC_READ) {
212+
if (ANY_BINSTR(arg)) VAL_TAIL(arg) += req->actual;
213+
}
214+
else if (req->command == RDC_WRITE) {
215+
SET_NONE(arg); // Write is done.
216+
}
217+
return R_NONE;
218+
case A_OPENQ:
219+
return R_TRUE;
220+
221+
case A_CLOSE:
222+
if (IS_OPEN(req)) {
223+
OS_DO_DEVICE(req, RDC_CLOSE);
224+
SET_CLOSED(req);
225+
}
226+
break;
227+
228+
default:
229+
Trap_Action(REB_PORT, action);
230+
}
231+
232+
return R_RET;
233+
}
234+
235+
236+
/***********************************************************************
237+
**
238+
*/ void Init_Serial_Scheme(void)
239+
/*
240+
***********************************************************************/
241+
{
242+
Register_Scheme(SYM_SERIAL, 0, Serial_Actor);
243+
}

0 commit comments

Comments
 (0)