diff --git a/libsigrok4DSL/backend.c b/libsigrok4DSL/backend.c index 46dc8042..5f5714af 100644 --- a/libsigrok4DSL/backend.c +++ b/libsigrok4DSL/backend.c @@ -23,6 +23,9 @@ #include "config.h" /* Needed for HAVE_LIBUSB_1_0 and others. */ #include "log.h" +#undef LOG_PREFIX +#define LOG_PREFIX "backend: " + /** * @mainpage libsigrok API * @@ -83,8 +86,8 @@ * called, which will (among other things) free the struct sr_context. * * Example for a minimal program using libsigrok: - * - + */ + /** * Sanity-check all libsigrok drivers. @@ -331,12 +334,9 @@ SR_API int sr_init(struct sr_context **ctx) context->libusb_ctx = NULL; context->hotplug_handle = 0; - context->hotplug_callback = NULL; - context->hotplug_user_data = NULL; + context->hotplug_callback = NULL; context->hotplug_tv.tv_sec = 0; - context->hotplug_tv.tv_usec = 0; - context->event_callback = NULL; - context->deiveList = NULL; + context->hotplug_tv.tv_usec = 0; ret = libusb_init(&context->libusb_ctx); if (LIBUSB_SUCCESS != ret) { @@ -386,7 +386,7 @@ LIBUSB_CALL int sr_hotplug_callback(struct libusb_context *ctx, struct libusb_de libusb_hotplug_event event, void *user_data){ if (user_data == NULL){ - sr_err("%s(): libsigrok usb event callback, userdata is NULL.", __func__); + sr_err("%s(): libsigrok usb event callback, userdata is NULL.", __func__); return 0; } @@ -398,13 +398,13 @@ LIBUSB_CALL int sr_hotplug_callback(struct libusb_context *ctx, struct libusb_de struct sr_context *user_ctx = (struct sr_context*)user_data; if (user_ctx->hotplug_callback != NULL){ - user_ctx->hotplug_callback(ctx, dev, ev, user_ctx->hotplug_user_data); + user_ctx->hotplug_callback(ctx, dev, ev); } return 0; } -SR_API int sr_listen_hotplug(struct sr_context *ctx, hotplug_event_callback callback, void *userdata) +SR_PRIV int sr_listen_hotplug(struct sr_context *ctx, hotplug_event_callback callback) { int ret; @@ -416,9 +416,9 @@ SR_API int sr_listen_hotplug(struct sr_context *ctx, hotplug_event_callback call sr_err("%s(): callback was NULL.", __func__); return SR_ERR; } + sr_info("%s", "Register hotplug callback."); ctx->hotplug_callback = callback; - ctx->hotplug_user_data = userdata; ret = libusb_hotplug_register_callback(ctx->libusb_ctx, (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), @@ -427,7 +427,7 @@ SR_API int sr_listen_hotplug(struct sr_context *ctx, hotplug_event_callback call LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, (libusb_hotplug_callback_fn)sr_hotplug_callback, - ctx, + ctx, //user data &ctx->hotplug_handle); if (LIBUSB_SUCCESS != ret){ return -1; @@ -436,25 +436,25 @@ SR_API int sr_listen_hotplug(struct sr_context *ctx, hotplug_event_callback call return 0; } -SR_API int sr_close_hotplug(struct sr_context *ctx) +SR_PRIV int sr_close_hotplug(struct sr_context *ctx) { if (!ctx) { sr_err("%s(): libsigrok context was NULL.", __func__); return SR_ERR; } - + sr_info("%s", "Unregister hotplug callback."); libusb_hotplug_deregister_callback(ctx->libusb_ctx, ctx->hotplug_handle); return 0; } -SR_API void sr_hotplug_wait_timout(struct sr_context *ctx) +SR_PRIV void sr_hotplug_wait_timout(struct sr_context *ctx) { if (!ctx) { sr_err("%s(): libsigrok context was NULL.", __func__); return; - } - libusb_handle_events_timeout(ctx->libusb_ctx, &ctx->hotplug_tv); + } + libusb_handle_events_timeout(ctx->libusb_ctx, &ctx->hotplug_tv); } /** @} */ diff --git a/libsigrok4DSL/hardware/DSL/dscope.c b/libsigrok4DSL/hardware/DSL/dscope.c index c6a6d605..69e86c7f 100644 --- a/libsigrok4DSL/hardware/DSL/dscope.c +++ b/libsigrok4DSL/hardware/DSL/dscope.c @@ -308,7 +308,7 @@ static GSList *scan(GSList *options) } else { char *firmware; - char *res_path = sr_get_firmware_res_path(); + char *res_path = DS_RES_PATH; if (!(firmware = g_try_malloc(strlen(res_path)+strlen(prof->firmware)+1))) { sr_err("Firmware path malloc error!"); return NULL; diff --git a/libsigrok4DSL/hardware/DSL/dsl.c b/libsigrok4DSL/hardware/DSL/dsl.c index e51e967d..27ad43fc 100644 --- a/libsigrok4DSL/hardware/DSL/dsl.c +++ b/libsigrok4DSL/hardware/DSL/dsl.c @@ -1919,7 +1919,7 @@ SR_PRIV int dsl_dev_open(struct sr_dev_driver *di, struct sr_dev_inst *sdi, gboo if (sdi->status == SR_ST_ACTIVE) { if (!(*fpga_done)) { char *fpga_bit; - char *res_path = sr_get_firmware_res_path(); + char *res_path = DS_RES_PATH; if (!(fpga_bit = g_try_malloc(strlen(res_path)+strlen(devc->profile->fpga_bit33)+1))) { sr_err("fpag_bit path malloc error!"); return SR_ERR_MALLOC; diff --git a/libsigrok4DSL/hardware/DSL/dslogic.c b/libsigrok4DSL/hardware/DSL/dslogic.c index 709f323a..1ec18d8b 100644 --- a/libsigrok4DSL/hardware/DSL/dslogic.c +++ b/libsigrok4DSL/hardware/DSL/dslogic.c @@ -379,7 +379,7 @@ static GSList *scan(GSList *options) } else { char *firmware; - char *res_path = sr_get_firmware_res_path(); + char *res_path = DS_RES_PATH; if (!(firmware = g_try_malloc(strlen(res_path)+strlen(prof->firmware)+1))) { sr_err("Firmware path malloc error!"); return NULL; @@ -1008,7 +1008,7 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi, ret = SR_ERR; } char *fpga_bit; - char *res_path = sr_get_firmware_res_path(); + char *res_path = DS_RES_PATH; if (!(fpga_bit = g_try_malloc(strlen(res_path)+strlen(devc->profile->fpga_bit33)+1))) { sr_err("fpag_bit path malloc error!"); return SR_ERR_MALLOC; diff --git a/libsigrok4DSL/lib_main.c b/libsigrok4DSL/lib_main.c index 88a4fc7f..c87b20cc 100644 --- a/libsigrok4DSL/lib_main.c +++ b/libsigrok4DSL/lib_main.c @@ -22,55 +22,68 @@ #include "libsigrok-internal.h" #include "log.h" -struct device_all_info -{ - struct sr_device_info _base_info; -}; +#ifdef _WIN32 + #include + #define _sleep(m) Sleep((m)) +#else + #include + #define _sleep(m) usleep((m) * 1000) +#endif -#define SR_DEVICE_MAX_COUNT 100 +#undef LOG_PREFIX +#define LOG_PREFIX "lib_main: " -static char DS_RES_PATH[500] = {0}; -static struct sr_context *g_sr_ctx = NULL; +char DS_RES_PATH[500] = {0}; +static struct sr_context *sr_ctx = NULL; +static libsigrok_event_callback_t event_callback = NULL; +static GList* all_device_list = NULL; // All device instance, sr_dev_inst* type +static GThread *hotplug_thread = NULL; + +static int sr_exit_flag = 0; +static int attach_event_flag = 0; +static int detach_event_flag = 0; +static int wait_redo_attch_flag = 0; +static int wait_redo_attch_times = 0; - //----------------------------private function---------------- - - /** - * Free device resource - */ - static sr_free_device(struct device_all_info *dev) - { - if (dev){ - free(dev); - } - } +static void hotplug_event_listen_callback(struct libusb_context *ctx, struct libusb_device *dev, int event); +static void usb_hotplug_process_proc(); /** * Must call first */ SR_API int sr_lib_init() -{ +{ int ret = 0; struct sr_dev_driver **drivers = NULL; struct sr_dev_driver **dr = NULL; - if (g_sr_ctx != NULL){ + if (sr_ctx != NULL){ return SR_ERR_HAVE_DONE; } - ret = sr_init(&g_sr_ctx); + ret = sr_init(&sr_ctx); if (ret != SR_OK){ return ret; } + sr_exit_flag = 0; // Initialise all libsigrok drivers drivers = sr_driver_list(); for (dr = drivers; *dr; dr++) { - if (sr_driver_init(g_sr_ctx, *dr) != SR_OK) { + if (sr_driver_init(sr_ctx, *dr) != SR_OK) { sr_err("Failed to initialize driver '%s'", (*dr)->name); return SR_ERR; } } + sr_ctx->hotplug_tv.tv_sec = 0; + sr_ctx->hotplug_tv.tv_usec = 0; + + sr_listen_hotplug(sr_ctx, hotplug_event_listen_callback); + + /** Start usb hotplug thread */ + hotplug_thread = g_thread_new("hotplug_proc", usb_hotplug_process_proc, NULL); + return SR_OK; } @@ -84,13 +97,22 @@ SR_API int sr_lib_exit() struct sr_dev_driver *driver_ins; GSList *l; struct sr_dev_inst *dev; - - if (g_sr_ctx == NULL){ + + if (sr_ctx == NULL){ return SR_ERR_HAVE_DONE; } + sr_close_hotplug(sr_ctx); + + sr_exit_flag = 1; //all thread to exit + + if (hotplug_thread != NULL){ + g_thread_join(hotplug_thread); + hotplug_thread = NULL; + } + // Release all device - for (l=g_sr_ctx->deiveList; l; l = l->next) + for (l = all_device_list; l; l = l->next) { dev = l->data; if (dev && dev->driver) @@ -103,12 +125,13 @@ SR_API int sr_lib_exit() driver_ins->dev_close(dev); } } - g_safe_free_list(g_sr_ctx->deiveList); + g_safe_free_list(all_device_list); + - if (sr_exit(g_sr_ctx) != SR_OK){ + if (sr_exit(sr_ctx) != SR_OK){ sr_err("%s", "call sr_exit error"); } - g_sr_ctx = NULL; + sr_ctx = NULL; return SR_OK; } @@ -129,21 +152,84 @@ SR_API void sr_set_firmware_resource_dir(const char *dir) } } -SR_PRIV char* sr_get_firmware_res_path() -{ - return DS_RES_PATH; -} - /** * Set event callback, event type see enum libsigrok_event_type */ SR_API void sr_set_event_callback(libsigrok_event_callback_t *cb) { - if (g_sr_ctx == NULL) - sr_lib_init(); - - if (g_sr_ctx != NULL){ - g_sr_ctx->event_callback = cb; + event_callback = cb; +} + + +/**-------------------private function ---------------*/ + +static int scan_hardware_device() +{ + +} + +static void hotplug_event_listen_callback(struct libusb_context *ctx, struct libusb_device *dev, int event) +{ + if (event == USB_EV_HOTPLUG_ATTACH){ + sr_info("One device attached."); + + if (wait_redo_attch_flag){ + sr_info("%s", "Device loose contact, but it reconnect success."); + } + wait_redo_attch_flag = 0; + attach_event_flag = 1; + } + else if (event == USB_EV_HOTPLUG_DETTACH){ + sr_info("One device detached."); + wait_redo_attch_flag = 1; //Begin wait the device reconnect, if timeout, will process the detach event. + wait_redo_attch_times = 0; + } + else{ + sr_err("%s", "Unknown usb event"); + wait_redo_attch_flag = 1; } } +static void process_attach_event() +{ + sr_info("%s", "Process device attch event."); +} + +static void process_detach_event() +{ + sr_info("%s", "Process device detach event."); +} + +static void usb_hotplug_process_proc() +{ + sr_info("%s", "Hotplug thread start!"); + + while (!sr_exit_flag) + { + sr_hotplug_wait_timout(sr_ctx); + + if (attach_event_flag){ + process_attach_event(); + attach_event_flag = 0; + } + if (detach_event_flag){ + process_detach_event(); + detach_event_flag = 0; + } + + _sleep(100); + + if (wait_redo_attch_flag){ + wait_redo_attch_times++; + + // 500ms + if (wait_redo_attch_times == 5){ + //Device loose contact,wait for it reconnection timeout. + detach_event_flag = 1; // use detach event + wait_redo_attch_flag = 0; + } + } + } + + sr_info("%s", "Hotplug thread end!"); +} \ No newline at end of file diff --git a/libsigrok4DSL/libsigrok-internal.h b/libsigrok4DSL/libsigrok-internal.h index 7670f4b5..805e77e8 100644 --- a/libsigrok4DSL/libsigrok-internal.h +++ b/libsigrok4DSL/libsigrok-internal.h @@ -48,17 +48,23 @@ #undef max #define max(a,b) ((a)>(b)?(a):(b)) +#define USB_EV_HOTPLUG_UNKNOW 0 +#define USB_EV_HOTPLUG_ATTACH 1 +#define USB_EV_HOTPLUG_DETTACH 2 + #define g_safe_free(p) if((p)) g_free((p)); ((p)) = NULL; #define g_safe_free_list(p) if((p)) g_slist_free((p)); ((p)) = NULL; +/** global variable */ +extern char DS_RES_PATH[500]; + +typedef void (*hotplug_event_callback)(struct libusb_context *ctx, struct libusb_device *dev, int event); + struct sr_context { libusb_context* libusb_ctx; libusb_hotplug_callback_handle hotplug_handle; hotplug_event_callback hotplug_callback; - void *hotplug_user_data; struct timeval hotplug_tv; - libsigrok_event_callback_t event_callback; - GList *deiveList; // All device instance, sr_dev_inst* type }; struct sr_session { @@ -182,6 +188,7 @@ SR_PRIV int sr_session_source_add_channel(GIOChannel *channel, int events, SR_PRIV int sr_session_source_remove(int fd); SR_PRIV int sr_session_source_remove_pollfd(GPollFD *pollfd); SR_PRIV int sr_session_source_remove_channel(GIOChannel *channel); +SR_PRIV int sr_session_datafeed_callback_add(sr_datafeed_callback_t cb,void *cb_data); /*--- std.c -----------------------------------------------------------------*/ @@ -259,7 +266,10 @@ SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb); SR_PRIV int sr_init(struct sr_context **ctx); SR_PRIV int sr_exit(struct sr_context *ctx); -/*--- lib_main.c -------------------------------------------------*/ -SR_PRIV char* sr_get_firmware_res_path(); +SR_PRIV int sr_listen_hotplug(struct sr_context *ctx, hotplug_event_callback callback); +SR_PRIV int sr_close_hotplug(struct sr_context *ctx); +SR_PRIV void sr_hotplug_wait_timout(struct sr_context *ctx); +/*--- lib_main.c -------------------------------------------------*/ + #endif diff --git a/libsigrok4DSL/libsigrok.h b/libsigrok4DSL/libsigrok.h index de793a93..1f98cbde 100644 --- a/libsigrok4DSL/libsigrok.h +++ b/libsigrok4DSL/libsigrok.h @@ -160,11 +160,6 @@ enum { #define SR_PRIV #endif - -#define USB_EV_HOTPLUG_UNKNOW 0 -#define USB_EV_HOTPLUG_ATTACH 1 -#define USB_EV_HOTPLUG_DETTACH 2 - typedef unsigned long long sr_device_handle; enum sr_device_type{ @@ -1263,11 +1258,6 @@ struct ds_trigger_pos { /*--- backend.c -------------------------------------------------------------*/ //@event, 1:attach, 2:left -typedef void (*hotplug_event_callback)(void *context,void *device, int event, void *userdata); -SR_API int sr_listen_hotplug(struct sr_context *ctx, hotplug_event_callback callback, void *userdata); -SR_API int sr_close_hotplug(struct sr_context *ctx); -SR_API void sr_hotplug_wait_timout(struct sr_context *ctx); - SR_PRIV int sr_init(struct sr_context **ctx); SR_PRIV int sr_exit(struct sr_context *ctx); @@ -1327,8 +1317,7 @@ SR_API int sr_session_dev_list(GSList **devlist); /* Datafeed setup */ SR_API int sr_session_datafeed_callback_remove_all(void); -SR_API int sr_session_datafeed_callback_add(sr_datafeed_callback_t cb, - void *cb_data); + /* Session control */ SR_API int sr_session_start(void); @@ -1478,7 +1467,7 @@ SR_API void sr_set_firmware_resource_dir(const char *dir); /** * Get the device list, the last item is null. - * Call free to release buffer. If the list is empty, it returns null. + * User need call free() to release the buffer. If the list is empty, it returns null. */ SR_API struct sr_device_info* sr_device_get_list(int *out_count); @@ -1488,6 +1477,13 @@ SR_API struct sr_device_info* sr_device_get_list(int *out_count); */ SR_API int sr_device_select(sr_device_handle handle); +/** + * Active a device, if success, it will trigs the event of EV_CURRENT_DEVICE_CHANGED. + * If the old actived device is hardware, maybe user need store the data first. + * @index is -1, will select the last one. + */ +SR_API int sr_device_select_by_index(int index); + /** * Create a device from session file, it auto load the data. */ diff --git a/libsigrok4DSL/session.c b/libsigrok4DSL/session.c index 1db07e78..e029bf47 100644 --- a/libsigrok4DSL/session.c +++ b/libsigrok4DSL/session.c @@ -253,7 +253,7 @@ SR_API int sr_session_datafeed_callback_remove_all(void) * * @return SR_OK upon success, SR_ERR_BUG if no session exists. */ -SR_API int sr_session_datafeed_callback_add(sr_datafeed_callback_t cb, void *cb_data) +SR_PRIV int sr_session_datafeed_callback_add(sr_datafeed_callback_t cb, void *cb_data) { struct datafeed_callback *cb_struct; diff --git a/libsigrok4DSL/tests/test_main.c b/libsigrok4DSL/tests/test_main.c index 4cac2eaf..1eea2d85 100644 --- a/libsigrok4DSL/tests/test_main.c +++ b/libsigrok4DSL/tests/test_main.c @@ -1,8 +1,34 @@ #include +#include "../log.h" +#include -int main2() +#undef LOG_PREFIX +#define LOG_PREFIX "test_main: " + +int main() { + int ret = 0; + + if ((ret = sr_lib_init()) != SR_OK) + { + return 0; + } + sr_info("%s", "start."); + + char c = 0; + + while (1) + { + c = getchar(); + + if (c == 'x'){ + sr_lib_exit(); + sr_info("%s", "exit."); + break; + } + } + return 0; } \ No newline at end of file