libsigrok
|
00001 /* 00002 * This file is part of the sigrok project. 00003 * 00004 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com> 00005 * 00006 * This program is free software: you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation, either version 3 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include <sys/types.h> 00021 #include <sys/stat.h> 00022 #include <fcntl.h> 00023 #include <unistd.h> 00024 #include <sys/time.h> 00025 #include <zip.h> 00026 #include "sigrok.h" 00027 #include "sigrok-internal.h" 00028 00029 /* size of payloads sent across the session bus */ 00030 #define CHUNKSIZE (512 * 1024) 00031 00032 struct session_vdev { 00033 char *capturefile; 00034 struct zip *archive; 00035 struct zip_file *capfile; 00036 int bytes_read; 00037 uint64_t samplerate; 00038 int unitsize; 00039 int num_probes; 00040 }; 00041 00042 static char *sessionfile = NULL; 00043 static GSList *dev_insts = NULL; 00044 static int hwcaps[] = { 00045 SR_HWCAP_CAPTUREFILE, 00046 SR_HWCAP_CAPTURE_UNITSIZE, 00047 0, 00048 }; 00049 00050 /** 00051 * TODO. 00052 * 00053 * @param dev_index TODO. 00054 */ 00055 static struct session_vdev *get_vdev_by_index(int dev_index) 00056 { 00057 struct sr_dev_inst *sdi; 00058 struct session_vdev *vdev; 00059 00060 /* TODO: Sanity checks on dev_index. */ 00061 00062 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) { 00063 sr_err("session driver: %s: device instance with device " 00064 "index %d was not found", __func__, dev_index); 00065 return NULL; 00066 } 00067 00068 /* TODO: Is sdi->priv == NULL valid? */ 00069 00070 vdev = sdi->priv; 00071 00072 return vdev; 00073 } 00074 00075 /** 00076 * TODO. 00077 * 00078 * @param fd TODO. 00079 * @param revents TODO. 00080 * @param cb_data TODO. 00081 * 00082 * @return TODO. 00083 */ 00084 static int receive_data(int fd, int revents, void *cb_data) 00085 { 00086 struct sr_dev_inst *sdi; 00087 struct session_vdev *vdev; 00088 struct sr_datafeed_packet packet; 00089 struct sr_datafeed_logic logic; 00090 GSList *l; 00091 void *buf; 00092 int ret, got_data; 00093 00094 /* Avoid compiler warnings. */ 00095 (void)fd; 00096 (void)revents; 00097 00098 sr_dbg("session_driver: feed chunk"); 00099 00100 got_data = FALSE; 00101 for (l = dev_insts; l; l = l->next) { 00102 sdi = l->data; 00103 vdev = sdi->priv; 00104 if (!vdev) 00105 /* already done with this instance */ 00106 continue; 00107 00108 if (!(buf = g_try_malloc(CHUNKSIZE))) { 00109 sr_err("session driver: %s: buf malloc failed", 00110 __func__); 00111 return FALSE; /* TODO: SR_ERR_MALLOC */ 00112 } 00113 00114 ret = zip_fread(vdev->capfile, buf, CHUNKSIZE); 00115 if (ret > 0) { 00116 got_data = TRUE; 00117 packet.type = SR_DF_LOGIC; 00118 packet.payload = &logic; 00119 logic.length = ret; 00120 logic.unitsize = vdev->unitsize; 00121 logic.data = buf; 00122 vdev->bytes_read += ret; 00123 sr_session_send(cb_data, &packet); 00124 } else { 00125 /* done with this capture file */ 00126 zip_fclose(vdev->capfile); 00127 g_free(vdev->capturefile); 00128 g_free(vdev); 00129 sdi->priv = NULL; 00130 } 00131 } 00132 00133 if (!got_data) { 00134 packet.type = SR_DF_END; 00135 sr_session_send(cb_data, &packet); 00136 } 00137 00138 return TRUE; 00139 } 00140 00141 /* driver callbacks */ 00142 static int hw_cleanup(void); 00143 00144 /** 00145 * TODO. 00146 * 00147 * @param devinfo TODO. 00148 * 00149 * @return TODO. 00150 */ 00151 static int hw_init(const char *devinfo) 00152 { 00153 sessionfile = g_strdup(devinfo); 00154 00155 return 0; 00156 } 00157 00158 /** 00159 * TODO. 00160 */ 00161 static int hw_cleanup(void) 00162 { 00163 GSList *l; 00164 00165 for (l = dev_insts; l; l = l->next) 00166 sr_dev_inst_free(l->data); 00167 g_slist_free(dev_insts); 00168 dev_insts = NULL; 00169 00170 sr_session_source_remove(-1); 00171 00172 g_free(sessionfile); 00173 00174 return SR_OK; 00175 } 00176 00177 static int hw_dev_open(int dev_index) 00178 { 00179 struct sr_dev_inst *sdi; 00180 00181 sdi = sr_dev_inst_new(dev_index, SR_ST_INITIALIZING, 00182 NULL, NULL, NULL); 00183 if (!sdi) 00184 return SR_ERR; 00185 00186 if (!(sdi->priv = g_try_malloc0(sizeof(struct session_vdev)))) { 00187 sr_err("session driver: %s: sdi->priv malloc failed", __func__); 00188 return SR_ERR_MALLOC; 00189 } 00190 00191 dev_insts = g_slist_append(dev_insts, sdi); 00192 00193 return SR_OK; 00194 } 00195 00196 static void *hw_dev_info_get(int dev_index, int dev_info_id) 00197 { 00198 struct session_vdev *vdev; 00199 void *info; 00200 00201 if (dev_info_id != SR_DI_CUR_SAMPLERATE) 00202 return NULL; 00203 00204 if (!(vdev = get_vdev_by_index(dev_index))) 00205 return NULL; 00206 00207 info = &vdev->samplerate; 00208 00209 return info; 00210 } 00211 00212 static int hw_dev_status_get(int dev_index) 00213 { 00214 /* Avoid compiler warnings. */ 00215 (void)dev_index; 00216 00217 if (sr_dev_list() != NULL) 00218 return SR_OK; 00219 else 00220 return SR_ERR; 00221 } 00222 00223 /** 00224 * Get the list of hardware capabilities. 00225 * 00226 * @return A pointer to the (hardware) capabilities of this virtual session 00227 * driver. This could be NULL, if no such capabilities exist. 00228 */ 00229 static int *hw_hwcap_get_all(void) 00230 { 00231 return hwcaps; 00232 } 00233 00234 static int hw_dev_config_set(int dev_index, int hwcap, void *value) 00235 { 00236 struct session_vdev *vdev; 00237 uint64_t *tmp_u64; 00238 00239 if (!(vdev = get_vdev_by_index(dev_index))) 00240 return SR_ERR; 00241 00242 switch (hwcap) { 00243 case SR_HWCAP_SAMPLERATE: 00244 tmp_u64 = value; 00245 vdev->samplerate = *tmp_u64; 00246 sr_info("session driver: setting samplerate to %" PRIu64, 00247 vdev->samplerate); 00248 break; 00249 case SR_HWCAP_CAPTUREFILE: 00250 vdev->capturefile = g_strdup(value); 00251 sr_info("session driver: setting capturefile to %s", 00252 vdev->capturefile); 00253 break; 00254 case SR_HWCAP_CAPTURE_UNITSIZE: 00255 tmp_u64 = value; 00256 vdev->unitsize = *tmp_u64; 00257 break; 00258 case SR_HWCAP_CAPTURE_NUM_PROBES: 00259 tmp_u64 = value; 00260 vdev->num_probes = *tmp_u64; 00261 break; 00262 default: 00263 sr_err("session driver: %s: unknown capability %d requested", 00264 __func__, hwcap); 00265 return SR_ERR; 00266 } 00267 00268 return SR_OK; 00269 } 00270 00271 static int hw_dev_acquisition_start(int dev_index, void *cb_data) 00272 { 00273 struct zip_stat zs; 00274 struct session_vdev *vdev; 00275 struct sr_datafeed_header *header; 00276 struct sr_datafeed_packet *packet; 00277 int ret; 00278 00279 if (!(vdev = get_vdev_by_index(dev_index))) 00280 return SR_ERR; 00281 00282 sr_info("session_driver: opening archive %s file %s", sessionfile, 00283 vdev->capturefile); 00284 00285 if (!(vdev->archive = zip_open(sessionfile, 0, &ret))) { 00286 sr_err("session driver: Failed to open session file '%s': " 00287 "zip error %d\n", sessionfile, ret); 00288 return SR_ERR; 00289 } 00290 00291 if (zip_stat(vdev->archive, vdev->capturefile, 0, &zs) == -1) { 00292 sr_err("session driver: Failed to check capture file '%s' in " 00293 "session file '%s'.", vdev->capturefile, sessionfile); 00294 return SR_ERR; 00295 } 00296 00297 if (!(vdev->capfile = zip_fopen(vdev->archive, vdev->capturefile, 0))) { 00298 sr_err("session driver: Failed to open capture file '%s' in " 00299 "session file '%s'.", vdev->capturefile, sessionfile); 00300 return SR_ERR; 00301 } 00302 00303 /* freewheeling source */ 00304 sr_session_source_add(-1, 0, 0, receive_data, cb_data); 00305 00306 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) { 00307 sr_err("session driver: %s: packet malloc failed", __func__); 00308 return SR_ERR_MALLOC; 00309 } 00310 00311 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) { 00312 sr_err("session driver: %s: header malloc failed", __func__); 00313 return SR_ERR_MALLOC; 00314 } 00315 00316 /* Send header packet to the session bus. */ 00317 packet->type = SR_DF_HEADER; 00318 packet->payload = (unsigned char *)header; 00319 header->feed_version = 1; 00320 gettimeofday(&header->starttime, NULL); 00321 header->samplerate = vdev->samplerate; 00322 header->num_logic_probes = vdev->num_probes; 00323 sr_session_send(cb_data, packet); 00324 g_free(header); 00325 g_free(packet); 00326 00327 return SR_OK; 00328 } 00329 00330 SR_PRIV struct sr_dev_driver session_driver = { 00331 .name = "session", 00332 .longname = "Session-emulating driver", 00333 .api_version = 1, 00334 .init = hw_init, 00335 .cleanup = hw_cleanup, 00336 .dev_open = hw_dev_open, 00337 .dev_close = NULL, 00338 .dev_info_get = hw_dev_info_get, 00339 .dev_status_get = hw_dev_status_get, 00340 .hwcap_get_all = hw_hwcap_get_all, 00341 .dev_config_set = hw_dev_config_set, 00342 .dev_acquisition_start = hw_dev_acquisition_start, 00343 .dev_acquisition_stop = NULL, 00344 };