From: Bert Vermeulen Date: Sun, 8 Jul 2012 21:48:04 +0000 (+0200) Subject: genericdmm: more flexible device discovery X-Git-Tag: dsupstream~837 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=bbb40871c88bbb622a275785d4aaf1e5e5a927f9;p=libsigrok.git genericdmm: more flexible device discovery --- diff --git a/hardware/genericdmm/api.c b/hardware/genericdmm/api.c index e1e94098..b744bc18 100644 --- a/hardware/genericdmm/api.c +++ b/hardware/genericdmm/api.c @@ -46,9 +46,9 @@ static const int hwcaps[] = { SR_HWCAP_LIMIT_SAMPLES, SR_HWCAP_LIMIT_MSEC, SR_HWCAP_CONTINUOUS, - SR_HWCAP_MODEL, - SR_HWCAP_CONN, - SR_HWCAP_SERIALCOMM, + SR_HWOPT_MODEL, + SR_HWOPT_CONN, + SR_HWOPT_SERIALCOMM, 0, }; @@ -63,6 +63,130 @@ static struct sr_dev_driver *gdi = &genericdmm_driver_info; SR_PRIV libusb_context *genericdmm_usb_context = NULL; +static GSList *connect_usb(const char *conn) +{ + struct sr_dev_inst *sdi; + struct context *ctx; + libusb_device **devlist; + struct libusb_device_descriptor des; + GSList *devices; + GRegex *reg; + GMatchInfo *match; + int vid, pid, bus, addr, devcnt, err, i; + char *mstr; + + vid = pid = bus = addr = 0; + reg = g_regex_new(DMM_CONN_USB_VIDPID, 0, 0, NULL); + if (g_regex_match(reg, conn, 0, &match)) { + /* Extract VID. */ + if ((mstr = g_match_info_fetch(match, 1))) + vid = strtoul(mstr, NULL, 16); + g_free(mstr); + + /* Extract PID. */ + if ((mstr = g_match_info_fetch(match, 2))) + pid = strtoul(mstr, NULL, 16); + g_free(mstr); + } else { + g_match_info_unref(match); + g_regex_unref(reg); + reg = g_regex_new(DMM_CONN_USB_BUSADDR, 0, 0, NULL); + if (g_regex_match(reg, conn, 0, &match)) { + /* Extract bus. */ + if ((mstr = g_match_info_fetch(match, 0))) + bus = strtoul(mstr, NULL, 16); + g_free(mstr); + + /* Extract address. */ + if ((mstr = g_match_info_fetch(match, 0))) + addr = strtoul(mstr, NULL, 16); + g_free(mstr); + } + } + g_match_info_unref(match); + g_regex_unref(reg); + + if (vid + pid + bus + addr == 0) + return NULL; + + if (bus > 64) { + sr_err("invalid bus"); + return NULL; + } + + if (addr > 127) { + sr_err("invalid address"); + return NULL; + } + + /* Looks like a valid USB device specification, but is it connected? */ + devices = NULL; + libusb_get_device_list(genericdmm_usb_context, &devlist); + for (i = 0; devlist[i]; i++) { + if ((err = libusb_get_device_descriptor(devlist[i], &des))) { + sr_err("genericdmm: failed to get device descriptor: %d", err); + continue; + } + + if (vid + pid && (des.idVendor != vid || des.idProduct != pid)) + /* VID/PID specified, but no match. */ + continue; + + if (bus + addr && ( + libusb_get_bus_number(devlist[i]) != bus + || libusb_get_device_address(devlist[i]) != addr)) + /* Bus/address specified, but no match. */ + continue; + + /* Found one. */ + if (!(ctx = g_try_malloc0(sizeof(struct context)))) { + sr_err("genericdmm: ctx malloc failed."); + return 0; + } + + devcnt = g_slist_length(gdi->instances); + if (!(sdi = sr_dev_inst_new(devcnt, SR_ST_ACTIVE, + "Generic DMM", NULL, NULL))) { + sr_err("genericdmm: sr_dev_inst_new returned NULL."); + return NULL; + } + sdi->priv = ctx; + ctx->usb = sr_usb_dev_inst_new( + libusb_get_bus_number(devlist[i]), + libusb_get_device_address(devlist[i]), NULL); + devices = g_slist_append(devices, sdi); + } + libusb_free_device_list(devlist, 1); + + return devices; +} + +static GSList *connect_serial(const char *conn, const char *serialcomm) +{ + GSList *devices; + + devices = NULL; + + /* TODO */ + sr_dbg("not yet implemented"); + + return devices; +} + +GSList *genericdmm_connect(const char *conn, const char *serialcomm) +{ + GSList *devices; + + if (serialcomm) + /* Must be a serial port. */ + return connect_serial(conn, serialcomm); + + if ((devices = connect_usb(conn))) + return devices; + + return NULL; +} + static int hw_init(void) { @@ -282,179 +406,10 @@ static const int *hw_hwcap_get_all(void) return hwcaps; } -static int parse_conn_vidpid(struct sr_dev_inst *sdi, const char *conn) -{ - struct context *ctx; - libusb_device **devlist; - struct libusb_device_descriptor des; - GRegex *reg; - GMatchInfo *match; - int vid, pid, found, err, i; - char *vidstr, *pidstr; - - found = FALSE; - - reg = g_regex_new(DMM_CONN_USB_VIDPID, 0, 0, NULL); - if (g_regex_match(reg, conn, 0, &match)) { - /* Extract VID. */ - if (!(vidstr = g_match_info_fetch(match, 0))) { - sr_err("failed to fetch VID from regex"); - goto err; - } - vid = strtoul(vidstr, NULL, 16); - g_free(vidstr); - if (vid > 0xffff) { - sr_err("invalid VID"); - goto err; - } - - /* Extract PID. */ - if (!(pidstr = g_match_info_fetch(match, 0))) { - sr_err("failed to fetch PID from regex"); - goto err; - } - pid = strtoul(pidstr, NULL, 16); - g_free(pidstr); - if (pid > 0xffff) { - sr_err("invalid PID"); - goto err; - } - - /* Looks like a valid VID:PID, but is it connected? */ - libusb_get_device_list(genericdmm_usb_context, &devlist); - for (i = 0; devlist[i]; i++) { - if ((err = libusb_get_device_descriptor(devlist[i], &des))) { - sr_err("genericdmm: failed to get device descriptor: %d", err); - goto err; - } - - if (des.idVendor == vid && des.idProduct == pid) { - ctx = sdi->priv; - ctx->usb = sr_usb_dev_inst_new( - libusb_get_bus_number(devlist[i]), - libusb_get_device_address(devlist[i]), NULL); - found = TRUE; - break; - } - } - libusb_free_device_list(devlist, 1); - } - -err: - if (match) - g_match_info_unref(match); - g_regex_unref(reg); - - return found; -} - -static int parse_conn_busaddr(struct sr_dev_inst *sdi, const char *conn) -{ - struct context *ctx; - libusb_device **devlist; - struct libusb_device_descriptor des; - GRegex *reg; - GMatchInfo *match; - int bus, addr, found, err, i; - char *busstr, *addrstr; - - found = FALSE; - - reg = g_regex_new(DMM_CONN_USB_BUSADDR, 0, 0, NULL); - if (g_regex_match(reg, conn, 0, &match)) { - /* Extract bus. */ - if (!(busstr = g_match_info_fetch(match, 0))) { - sr_err("failed to fetch bus from regex"); - goto err; - } - bus = strtoul(busstr, NULL, 16); - g_free(busstr); - if (bus > 64) { - sr_err("invalid bus"); - goto err; - } - - /* Extract address. */ - if (!(addrstr = g_match_info_fetch(match, 0))) { - sr_err("failed to fetch address from regex"); - goto err; - } - addr = strtoul(addrstr, NULL, 16); - g_free(addrstr); - if (addr > 127) { - sr_err("invalid address"); - goto err; - } - - /* Looks like a valid bus/address, but is it connected? */ - libusb_get_device_list(genericdmm_usb_context, &devlist); - for (i = 0; devlist[i]; i++) { - if ((err = libusb_get_device_descriptor(devlist[i], &des))) { - sr_err("genericdmm: failed to get device descriptor: %d", err); - goto err; - } - - if (libusb_get_bus_number(devlist[i]) == bus - && libusb_get_device_address(devlist[i]) == addr) { - ctx = sdi->priv; - ctx->usb = sr_usb_dev_inst_new(bus, addr, NULL); - found = TRUE; - break; - } - } - libusb_free_device_list(devlist, 1); - } - -err: - if (match) - g_match_info_unref(match); - g_regex_unref(reg); - - return found; -} - -static int parse_conn_serial(struct sr_dev_inst *sdi, const char *conn) -{ - int found; - - found = FALSE; - - /* TODO */ - - return found; -} - -static int parse_conn(struct sr_dev_inst *sdi, const char *conn) -{ - - if (parse_conn_vidpid(sdi, conn)) - return SR_OK; - - if (parse_conn_busaddr(sdi, conn)) - return SR_OK; - - if (parse_conn_serial(sdi, conn)) - return SR_OK; - - sr_err("Invalid connection specification"); - - return SR_ERR; -} - -static int parse_serialcomm(struct sr_dev_inst *sdi, const char *conn) -{ - - /* TODO */ - /* set ctx->serial_* */ - - return SR_OK; -} - static int hw_dev_config_set(int dev_index, int hwcap, const void *value) { struct sr_dev_inst *sdi; struct context *ctx; - int i; if (!(sdi = sr_dev_inst_get(gdi->instances, dev_index))) { sr_err("genericdmm: sdi was NULL."); @@ -483,36 +438,6 @@ static int hw_dev_config_set(int dev_index, int hwcap, const void *value) sr_dbg("genericdmm: Setting LIMIT_SAMPLES to %" PRIu64 ".", ctx->limit_samples); break; - case SR_HWCAP_MODEL: - for (i = 0; dev_profiles[i].model; i++) { - if (!strcasecmp(dev_profiles[i].model, value)) { - ctx->profile = &dev_profiles[i]; - /* Frontends access these fields directly, so we - * need to copy them over. */ - sdi->vendor = g_strdup(dev_profiles[i].vendor); - sdi->model = g_strdup(dev_profiles[i].model); - /* This is the first time we actually know which - * DMM chip we're talking to, so let's init - * anything specific to it now */ - if (ctx->profile->chip->init) - if (ctx->profile->chip->init(ctx) != SR_OK) - return SR_ERR; - break; - } - } - if (!ctx->profile) { - sr_err("unknown model %s", value); - return SR_ERR; - } - break; - case SR_HWCAP_CONN: - if (parse_conn(sdi, value) != SR_OK) - return SR_ERR_ARG; - break; - case SR_HWCAP_SERIALCOMM: - if (parse_serialcomm(sdi, value) != SR_OK) - return SR_ERR_ARG; - break; default: sr_err("genericdmm: Unknown capability: %d.", hwcap); return SR_ERR;