]> sigrok.org Git - libsigrok.git/commitdiff
genericdmm: more flexible device discovery
authorBert Vermeulen <redacted>
Sun, 8 Jul 2012 21:48:04 +0000 (23:48 +0200)
committerBert Vermeulen <redacted>
Fri, 3 Aug 2012 08:27:37 +0000 (10:27 +0200)
hardware/genericdmm/api.c

index e1e94098015b25e2cf4339fa0450beba48994338..b744bc18beae4c5c3c249415c2478a31478843d6 100644 (file)
@@ -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;