1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013 Aurelien Jacobs <aurel@gnuage.org>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <config.h>
21 #include <string.h>
22 #include "protocol.h"
23 
24 static const uint32_t scanopts[] = {
25 	SR_CONF_CONN,
26 	SR_CONF_SERIALCOMM,
27 };
28 
29 static const uint32_t drvopts[] = {
30 	SR_CONF_THERMOMETER,
31 };
32 
33 static const uint32_t devopts[] = {
34 	SR_CONF_CONTINUOUS,
35 	SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
36 	SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
37 	SR_CONF_DATA_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
38 };
39 
40 static const char *data_sources[] = {
41 	"Live",
42 	"Memory",
43 };
44 
scan(struct sr_dev_driver * di,GSList * options)45 static GSList *scan(struct sr_dev_driver *di, GSList *options)
46 {
47 	struct dev_context *devc;
48 	struct sr_serial_dev_inst *serial;
49 	struct sr_dev_inst *sdi;
50 	struct sr_config *src;
51 	GSList *devices, *l;
52 	const char *conn, *serialcomm;
53 	uint8_t buf[50];
54 	size_t len;
55 
56 	len = sizeof(buf);
57 	devices = NULL;
58 	conn = serialcomm = NULL;
59 	for (l = options; l; l = l->next) {
60 		src = l->data;
61 		switch (src->key) {
62 		case SR_CONF_CONN:
63 			conn = g_variant_get_string(src->data, NULL);
64 			break;
65 		case SR_CONF_SERIALCOMM:
66 			serialcomm = g_variant_get_string(src->data, NULL);
67 			break;
68 		}
69 	}
70 	if (!conn)
71 		return NULL;
72 	if (!serialcomm)
73 		serialcomm = "9600/8n1";
74 
75 	serial = sr_serial_dev_inst_new(conn, serialcomm);
76 
77 	if (serial_open(serial, SERIAL_RDONLY) != SR_OK)
78 		return NULL;
79 
80 	sr_info("Probing serial port %s.", conn);
81 
82 	serial_flush(serial);
83 
84 	/* Let's get a bit of data and see if we can find a packet. */
85 	if (serial_stream_detect(serial, buf, &len, 25,
86 			appa_55ii_packet_valid, 500) != SR_OK)
87 		goto scan_cleanup;
88 
89 	sr_info("Found device on port %s.", conn);
90 
91 	sdi = g_malloc0(sizeof(struct sr_dev_inst));
92 	sdi->status = SR_ST_INACTIVE;
93 	sdi->vendor = g_strdup("APPA");
94 	sdi->model = g_strdup("55II");
95 	devc = g_malloc0(sizeof(struct dev_context));
96 	devc->data_source = DEFAULT_DATA_SOURCE;
97 	sdi->inst_type = SR_INST_SERIAL;
98 	sdi->conn = serial;
99 	sdi->priv = devc;
100 
101 	sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "T1");
102 	sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "T2");
103 
104 	devices = g_slist_append(devices, sdi);
105 
106 scan_cleanup:
107 	serial_close(serial);
108 
109 	return std_scan_complete(di, devices);
110 }
111 
config_get(uint32_t key,GVariant ** data,const struct sr_dev_inst * sdi,const struct sr_channel_group * cg)112 static int config_get(uint32_t key, GVariant **data,
113 	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
114 {
115 	struct dev_context *devc = sdi->priv;
116 
117 	(void)cg;
118 
119 	switch (key) {
120 	case SR_CONF_LIMIT_SAMPLES:
121 	case SR_CONF_LIMIT_MSEC:
122 		return sr_sw_limits_config_get(&devc->limits, key, data);
123 	case SR_CONF_DATA_SOURCE:
124 		*data = g_variant_new_string(data_sources[devc->data_source]);
125 		break;
126 	default:
127 		return SR_ERR_NA;
128 	}
129 
130 	return SR_OK;
131 }
132 
config_set(uint32_t key,GVariant * data,const struct sr_dev_inst * sdi,const struct sr_channel_group * cg)133 static int config_set(uint32_t key, GVariant *data,
134 	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
135 {
136 	struct dev_context *devc;
137 	int idx;
138 
139 	(void)cg;
140 
141 	devc = sdi->priv;
142 
143 	switch (key) {
144 	case SR_CONF_LIMIT_SAMPLES:
145 	case SR_CONF_LIMIT_MSEC:
146 		return sr_sw_limits_config_set(&devc->limits, key, data);
147 	case SR_CONF_DATA_SOURCE:
148 		if ((idx = std_str_idx(data, ARRAY_AND_SIZE(data_sources))) < 0)
149 			return SR_ERR_ARG;
150 		devc->data_source = idx;
151 		break;
152 	default:
153 		return SR_ERR_NA;
154 	}
155 
156 	return SR_OK;
157 }
158 
config_list(uint32_t key,GVariant ** data,const struct sr_dev_inst * sdi,const struct sr_channel_group * cg)159 static int config_list(uint32_t key, GVariant **data,
160 	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
161 {
162 	switch (key) {
163 	case SR_CONF_SCAN_OPTIONS:
164 	case SR_CONF_DEVICE_OPTIONS:
165 		return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
166 	case SR_CONF_DATA_SOURCE:
167 		*data = g_variant_new_strv(ARRAY_AND_SIZE(data_sources));
168 		break;
169 	default:
170 		return SR_ERR_NA;
171 	}
172 
173 	return SR_OK;
174 }
175 
dev_acquisition_start(const struct sr_dev_inst * sdi)176 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
177 {
178 	struct sr_serial_dev_inst *serial;
179 	struct dev_context *devc;
180 
181 	serial = sdi->conn;
182 	devc = sdi->priv;
183 
184 	sr_sw_limits_acquisition_start(&devc->limits);
185 
186 	std_session_send_df_header(sdi);
187 
188 	serial_source_add(sdi->session, serial, G_IO_IN, 50,
189 			appa_55ii_receive_data, (void *)sdi);
190 
191 	return SR_OK;
192 }
193 
194 static struct sr_dev_driver appa_55ii_driver_info = {
195 	.name = "appa-55ii",
196 	.longname = "APPA 55II",
197 	.api_version = 1,
198 	.init = std_init,
199 	.cleanup = std_cleanup,
200 	.scan = scan,
201 	.dev_list = std_dev_list,
202 	.dev_clear = std_dev_clear,
203 	.config_get = config_get,
204 	.config_set = config_set,
205 	.config_list = config_list,
206 	.dev_open = std_serial_dev_open,
207 	.dev_close = std_serial_dev_close,
208 	.dev_acquisition_start = dev_acquisition_start,
209 	.dev_acquisition_stop = std_serial_dev_acquisition_stop,
210 	.context = NULL,
211 };
212 SR_REGISTER_DEV_DRIVER(appa_55ii_driver_info);
213