Ejemplo n.º 1
0
int
gp_port_library_list (GPPortInfoList *list)
{
	GPPortInfo info;
#ifdef HAVE_MDNS_BONJOUR
	DNSServiceRef		sd;
	DNSServiceErrorType	ret;
	int			fd;
	fd_set			infds;
	struct timeval		tv;
#endif

	gp_port_info_new (&info);
	gp_port_info_set_type (info, GP_PORT_PTPIP);
	gp_port_info_set_name (info, _("PTP/IP Connection"));
	gp_port_info_set_path (info, "ptpip:");
	CHECK (gp_port_info_list_append (list, info));

	/* Generic matcher so you can pass any IP address */
	gp_port_info_new (&info);
	gp_port_info_set_type (info, GP_PORT_PTPIP);
	gp_port_info_set_name (info, "");
	gp_port_info_set_path (info, "^ptpip:");
	CHECK (gp_port_info_list_append (list, info));

#ifdef HAVE_MDNS_BONJOUR
	ret = DNSServiceBrowse (
		&sd,
		0,	/* unused flags */
		0,	/* all ifaces */
		"_ptp._tcp",
		NULL,
		_ptpip_enumerate,
		list
	);
	/* We need to make it a non-blocking query */
	fd = DNSServiceRefSockFD(sd);
	if (fd != -1) {
		FD_ZERO (&infds); FD_SET (fd, &infds); 
		tv.tv_sec = 0; tv.tv_usec = 1;
		/* If we have input, we can try to process a result */
		if (1 == select (fd+1, &infds, NULL, NULL, &tv))
			DNSServiceProcessResult (sd);
	}
	DNSServiceRefDeallocate (sd);
#endif
	return GP_OK;
}
Ejemplo n.º 2
0
int
gp_port_library_list (GPPortInfoList *list)
{
    DIR *dir;
    struct dirent *dirent;
    int ret;
    GPPortInfo info;
    unsigned short vendor_id, product_id;

    dir = opendir ("/sys/class/scsi_generic");
    if (dir == NULL)
        return GP_OK;

    while ((dirent = readdir (dir))) {
        char path[4096];
        if (gp_port_usbscsi_get_usb_id (dirent->d_name,
                                        &vendor_id, &product_id) != GP_OK)
            continue; /* Not a usb device */

        gp_port_info_new (&info);
        gp_port_info_set_type (info, GP_PORT_USB_SCSI);
        snprintf (path, sizeof (path),
                  "usbscsi:/dev/%s",
                  dirent->d_name);
        gp_port_info_set_path (info, path);
        gp_port_info_set_name (info, _("USB Mass Storage raw SCSI"));
        ret = gp_port_info_list_append (list, info);
        if (ret < GP_OK) /* can only be out of memory */
            break;
    }
    closedir (dir);
    return GP_OK;
}
Ejemplo n.º 3
0
int
gp_port_library_list (GPPortInfoList *list)
{
	GPPortInfo info;

	gp_log(GP_LOG_DEBUG,__FUNCTION__,"()");

        CHECK (gp_port_info_new (&info));
        gp_port_info_set_type (info, GP_PORT_USB);
        gp_port_info_set_name (info, "");
        gp_port_info_set_path (info, "^usb:");
        gp_port_info_list_append (list, info); /* do not check, might be -1 */

	gp_port_info_new (&info);
	gp_port_info_set_type (info, GP_PORT_USB);
	gp_port_info_set_name (info, "Universal Serial Bus");
	gp_port_info_set_path (info, "usb:001,001");
	CHECK (gp_port_info_list_append (list, info));
	return GP_OK;
}
Ejemplo n.º 4
0
static void
_ptpip_resolved (
	DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
	DNSServiceErrorType errorCode,
	const char *fullname, const char *hosttarget, uint16_t port,
	uint16_t txtLen, const char *txtRecord, void *context
) {
	struct hostent*	hent;
	struct in_addr	inaddr;
	GPPortInfo	*info;
	int		i, cnt;
	struct mdnsinfo	*mdnsi = context;
	char		path[200];

	if (errorCode != kDNSServiceErr_NoError) {
		gp_log (GP_LOG_ERROR, "ptpip", "Error on 2nd level query.");
		return;
	}
	gp_log (GP_LOG_DEBUG, "ptpip", "fullname %s, hosttarget %s, port %d", fullname, hosttarget, htons(port));
	cnt = TXTRecordGetCount (txtLen, txtRecord);
	for (i=0;i<cnt;i++) {
		char	key[256];
		uint8_t	valuelen;
		const void	*value;

		valuelen = 0;
		if (kDNSServiceErr_NoError == TXTRecordGetItemAtIndex (txtLen, txtRecord, i, sizeof(key), key, &valuelen, &value))
			gp_log (GP_LOG_DEBUG, "ptpip", "%d: %s:%s", i, key, (char*)value);
	}
	hent = gethostbyname (hosttarget);
	if (!hent) {
		gp_log (GP_LOG_ERROR, "ptpip", "Could not resolve the returned host: %s", hosttarget);
		return;
	}
	memcpy(&inaddr.s_addr,hent->h_addr_list[0],hent->h_length);
	gp_port_info_new (&info);
	gp_port_info_set_type (info, GP_PORT_PTPIP);
	gp_port_info_set_name (info, mdnsi->name);
	snprintf (path, sizeof(path), "ptpip:%s:%d", inet_ntoa(inaddr), htons(port));
	gp_port_info_set_path (info, path);
	gp_port_info_list_append (mdnsi->list, info);
}
Ejemplo n.º 5
0
int
gp_port_library_list (GPPortInfoList *list)
{
	DIR *dir;
	struct dirent *dirent;
	GPPortInfo info;
	int ret;
	unsigned short vendor_id, product_id;

	dir = opendir ("/sys/block");
	if (dir == NULL)
		return GP_OK;

	while ((dirent = readdir (dir))) {
		char path[4096];
		if (dirent->d_name[0] != 's' ||
		    dirent->d_name[1] != 'd' ||
		    dirent->d_name[2] < 'a' ||
		    dirent->d_name[2] > 'z')
			continue;

		if (gp_port_usbdiskdirect_get_usb_id (dirent->d_name,
				&vendor_id, &product_id) != GP_OK)
			continue; /* Not a usb device */

		gp_port_info_new (&info);
		gp_port_info_set_type (info, GP_PORT_USB_DISK_DIRECT);
		snprintf (path, sizeof (path),
			  "usbdiskdirect:/dev/%s",
			  dirent->d_name);
		gp_port_info_set_path (info, path);
		gp_port_info_set_name (info, _("USB Mass Storage direct IO"));
		ret = gp_port_info_list_append (list, info);
		if (ret < GP_OK)
			break;
	}
	closedir (dir);
	return GP_OK;
}
Ejemplo n.º 6
0
int
gp_port_library_list (GPPortInfoList *list)
{
	GPPortInfo	info;
	int		nrofdevices = 0;
	int		d, i, i1, i2, unknownint;
	libusb_context	*ctx;
	libusb_device	**devs = NULL;
	int		nrofdevs = 0;
	struct libusb_device_descriptor	*descs;

	C_LIBUSB (libusb_init (&ctx), GP_ERROR_IO);

	/* TODO: make sure libusb_exit gets called in all error paths inside this function */

	/* generic matcher. This will catch passed XXX,YYY entries for instance. */
	C_GP (gp_port_info_new (&info));
	gp_port_info_set_type (info, GP_PORT_USB);
	gp_port_info_set_name (info, "");
	gp_port_info_set_path (info, "^usb:");
	C_GP (gp_port_info_list_append (list, info));

	nrofdevs = libusb_get_device_list (ctx, &devs);
	C_MEM (descs = calloc (nrofdevs, sizeof(descs[0])));
	for (i=0;i<nrofdevs;i++)
		LOG_ON_LIBUSB_E (libusb_get_device_descriptor(devs[i], &descs[i]));

	for (d = 0; d < nrofdevs; d++) {
		/* Devices which are definitely not cameras. */
		if (	(descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
			(descs[d].bDeviceClass == LIBUSB_CLASS_COMM)	||
			(descs[d].bDeviceClass == 0xe0)	/* wireless / bluetooth */
		)
			continue;
		/* excepts HUBs, usually the interfaces have the classes, not
		 * the device */
		unknownint = 0;
		for (i = 0; i < descs[d].bNumConfigurations; i++) {
			struct libusb_config_descriptor *config;

			if (LOG_ON_LIBUSB_E (libusb_get_config_descriptor (devs[d], i, &config))) {
				unknownint++;
				continue;
			}
			for (i1 = 0; i1 < config->bNumInterfaces; i1++)
				for (i2 = 0; i2 < config->interface[i1].num_altsetting; i2++) {
					const struct libusb_interface_descriptor *intf = &config->interface[i1].altsetting[i2]; 
					if (	(intf->bInterfaceClass == LIBUSB_CLASS_HID)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_PRINTER)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_COMM)	||
						(intf->bInterfaceClass == 0xe0)	/* wireless/bluetooth*/
					)
						continue;
					unknownint++;
				}
			libusb_free_config_descriptor (config);
		}
		/* when we find only hids, printer or comm ifaces  ... skip this */
		if (!unknownint)
			continue;
		/* Note: We do not skip USB storage. Some devices can support both,
		 * and the Ricoh erronously reports it.
		 */ 
		nrofdevices++;
	}

#if 0
	/* If we already added usb:, and have 0 or 1 devices we have nothing to do.
	 * This should be the standard use case.
	 */
	/* We never want to return just "usb:" ... also return "usb:XXX,YYY", and
	 * let upper layers filter out the usb: */
	if (nrofdevices <= 1) 
		return (GP_OK);
#endif

	/* Redo the same bus/device walk, but now add the ports with usb:x,y notation,
	 * so we can address all USB devices.
	 */
	for (d = 0; d < nrofdevs; d++) {
		char path[200];

		/* Devices which are definitely not cameras. */
		if (	(descs[d].bDeviceClass == LIBUSB_CLASS_HUB)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_HID)		||
			(descs[d].bDeviceClass == LIBUSB_CLASS_PRINTER)	||
			(descs[d].bDeviceClass == LIBUSB_CLASS_COMM)
		)
			continue;
		/* excepts HUBs, usually the interfaces have the classes, not
		 * the device */
		unknownint = 0;
		for (i = 0; i < descs[d].bNumConfigurations; i++) {
			struct libusb_config_descriptor *config;

			if (LOG_ON_LIBUSB_E (libusb_get_config_descriptor (devs[d], i, &config))) {
				unknownint++;
				continue;
			}
			for (i1 = 0; i1 < config->bNumInterfaces; i1++)
				for (i2 = 0; i2 < config->interface[i1].num_altsetting; i2++) {
					const struct libusb_interface_descriptor *intf = &config->interface[i1].altsetting[i2]; 
					if (	(intf->bInterfaceClass == LIBUSB_CLASS_HID)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_PRINTER)	||
						(intf->bInterfaceClass == LIBUSB_CLASS_COMM))
						continue;
					unknownint++;
				}
			libusb_free_config_descriptor (config);
		}
		/* when we find only hids, printer or comm ifaces  ... skip this */
		if (!unknownint)
			continue;
		/* Note: We do not skip USB storage. Some devices can support both,
		 * and the Ricoh erronously reports it.
		 */ 
		C_GP (gp_port_info_new (&info));
		gp_port_info_set_type (info, GP_PORT_USB);
		gp_port_info_set_name (info, "Universal Serial Bus");
		snprintf (path,sizeof(path), "usb:%03d,%03d",
			libusb_get_bus_number (devs[d]),
			libusb_get_device_address (devs[d])
		);
		gp_port_info_set_path (info, path);
		C_GP (gp_port_info_list_append (list, info));
	}
	/* This will only be added if no other device was ever added.
	 * Users doing "usb:" usage will enter the regular expression matcher case. */
	if (nrofdevices == 0) {
		C_GP (gp_port_info_new (&info));
		gp_port_info_set_type (info, GP_PORT_USB);
		gp_port_info_set_name (info, "Universal Serial Bus");
		gp_port_info_set_path (info, "usb:");
		C_GP (gp_port_info_list_append (list, info));
	}
	libusb_free_device_list (devs, 1);
	libusb_exit (ctx); /* should free all stuff above */
	free (descs);
	return (GP_OK);
}
Ejemplo n.º 7
0
int
gp_port_library_list (GPPortInfoList *list)
{
	GPPortInfo info;
# ifdef HAVE_MNTENT_H
	FILE *mnt;
	struct mntent *mntent;
	char	path[1024];
	char	*s;
	struct stat stbuf;

	mnt = setmntent ("/etc/fstab", "r");
	if (mnt) {
		while ((mntent = getmntent (mnt))) {
			/* detect floppies so we don't access them with the stat() below */
			GP_LOG_D ("found fstab fsname %s", mntent->mnt_fsname);

			if ((NULL != strstr(mntent->mnt_fsname,"fd"))	||
			    (NULL != strstr(mntent->mnt_fsname,"floppy")) ||
			    (NULL != strstr(mntent->mnt_fsname,"fuse"))	||
			    (NULL != strstr(mntent->mnt_fsname,"nfs"))	||
			    (NULL != strstr(mntent->mnt_fsname,"cifs"))	||
			    (NULL != strstr(mntent->mnt_fsname,"smbfs"))||
			    (NULL != strstr(mntent->mnt_fsname,"afs"))	||
			    (NULL != strstr(mntent->mnt_fsname,"autofs"))||
                            (NULL != strstr(mntent->mnt_fsname,"cgroup"))||
                            (NULL != strstr(mntent->mnt_fsname,"systemd"))||
                            (NULL != strstr(mntent->mnt_fsname,"mqueue"))||
                            (NULL != strstr(mntent->mnt_fsname,"securityfs"))||
                            (NULL != strstr(mntent->mnt_fsname,"proc"))||
                            (NULL != strstr(mntent->mnt_fsname,"devtmpfs"))||
                            (NULL != strstr(mntent->mnt_fsname,"devpts"))||
                            (NULL != strstr(mntent->mnt_fsname,"sysfs"))||
			    (NULL != strstr(mntent->mnt_fsname,"gphotofs"))||
			/* fstype based */
			    (NULL != strstr(mntent->mnt_type,"autofs"))	||
			    (NULL != strstr(mntent->mnt_type,"nfs"))	||
			    (NULL != strstr(mntent->mnt_type,"smbfs"))||
			    (NULL != strstr(mntent->mnt_type,"proc"))||
			    (NULL != strstr(mntent->mnt_type,"sysfs"))||
			    (NULL != strstr(mntent->mnt_type,"cifs"))||
			    (NULL != strstr(mntent->mnt_type,"afs")) ||
			/* mount options */
				/* x-systemd.automount or similar */
			    (NULL != strstr(mntent->mnt_opts,"automount"))
			) {
				continue;
			}

			/* Whitelist some fuse based filesystems, e.g. to help exfat mounts */
			/* In general, if we are backed by a device, it is probably good(tm) */
			if (NULL != strstr(mntent->mnt_type,"fuse")) {
				if (!strstr(mntent->mnt_fsname,"/dev/"))
					continue;
			}

			snprintf (path, sizeof(path), "%s/DCIM", mntent->mnt_dir);
			if (-1 == stat(path, &stbuf)) {
				snprintf (path, sizeof(path), "%s/dcim", mntent->mnt_dir);
				if (-1 == stat(path, &stbuf))
					continue;
			}
			s = malloc (strlen(_("Media '%s'"))+strlen(mntent->mnt_fsname)+1);
			sprintf (s, _("Media '%s'"), mntent->mnt_fsname);
			gp_port_info_new (&info);
			gp_port_info_set_type (info, GP_PORT_DISK);
			gp_port_info_set_name (info, s);
			free (s);
			
			s = malloc (strlen("disk:")+strlen(mntent->mnt_dir)+1);
			sprintf (s, "disk:%s", mntent->mnt_dir);
			gp_port_info_set_path (info, s);
			if (gp_port_info_list_lookup_path (list, s) >= GP_OK) {
				free (s);
				continue;
			}
			free(s);
			CHECK (gp_port_info_list_append (list, info));
		}
		endmntent(mnt);
	}
	mnt = setmntent ("/etc/mtab", "r");
	if (mnt) {
		while ((mntent = getmntent (mnt))) {
			/* detect floppies so we don't access them with the stat() below */
			GP_LOG_D ("found mtab fsname %s", mntent->mnt_fsname);

			if ((NULL != strstr(mntent->mnt_fsname,"fd"))	||
			    (NULL != strstr(mntent->mnt_fsname,"floppy")) ||
			    (NULL != strstr(mntent->mnt_fsname,"fuse"))	||
			    (NULL != strstr(mntent->mnt_fsname,"nfs"))	||
			    (NULL != strstr(mntent->mnt_fsname,"cifs"))	||
			    (NULL != strstr(mntent->mnt_fsname,"smbfs"))||
			    (NULL != strstr(mntent->mnt_fsname,"afs"))	||
			    (NULL != strstr(mntent->mnt_fsname,"autofs"))||
                            (NULL != strstr(mntent->mnt_fsname,"cgroup"))||
                            (NULL != strstr(mntent->mnt_fsname,"systemd"))||
                            (NULL != strstr(mntent->mnt_fsname,"mqueue"))||
                            (NULL != strstr(mntent->mnt_fsname,"securityfs"))||
                            (NULL != strstr(mntent->mnt_fsname,"proc"))||
                            (NULL != strstr(mntent->mnt_fsname,"devtmpfs"))||
                            (NULL != strstr(mntent->mnt_fsname,"devpts"))||
                            (NULL != strstr(mntent->mnt_fsname,"sysfs"))||
			    (NULL != strstr(mntent->mnt_fsname,"gphotofs"))||
			/* fstype based */
			    (NULL != strstr(mntent->mnt_type,"autofs"))	||
			    (NULL != strstr(mntent->mnt_type,"nfs"))	||
			    (NULL != strstr(mntent->mnt_type,"smbfs"))||
			    (NULL != strstr(mntent->mnt_type,"proc"))||
			    (NULL != strstr(mntent->mnt_type,"sysfs"))||
			    (NULL != strstr(mntent->mnt_type,"cifs"))||
			    (NULL != strstr(mntent->mnt_type,"afs")) ||
			/* options */
			    (NULL != strstr(mntent->mnt_opts,"automount"))
			) {
				continue;
			}
			/* Whitelist some fuse based filesystems, e.g. to help exfat mounts */
			/* In general, if we are backed by a device, it is probably good(tm) */
			if (NULL != strstr(mntent->mnt_type,"fuse")) {
				if (!strstr(mntent->mnt_fsname,"/dev/"))
					continue;
			}

			snprintf (path, sizeof(path), "%s/DCIM", mntent->mnt_dir);
			if (-1 == stat(path, &stbuf)) {
				snprintf (path, sizeof(path), "%s/dcim", mntent->mnt_dir);
				if (-1 == stat(path, &stbuf))
					continue;
			}
			/* automount should be blacklist here, but we still need
			 * to look it up first otherwise the automounted camera
			 * won't appear.
			 */
			if (NULL != strstr(mntent->mnt_fsname, "automount")) {
				continue;
			}
			gp_port_info_new (&info);
			gp_port_info_set_type (info, GP_PORT_DISK);
			s = malloc (strlen(_("Media '%s'"))+strlen(mntent->mnt_fsname)+1);
			sprintf (s, _("Media '%s'"),  mntent->mnt_fsname);
			gp_port_info_set_name (info, s);
			free (s);
			
			s = malloc (strlen("disk:")+strlen(mntent->mnt_dir)+1);
			sprintf (s, "disk:%s", mntent->mnt_dir);
			gp_port_info_set_path (info, s);
			if (gp_port_info_list_lookup_path (list, s) >= GP_OK) {
				free (s);
				continue;
			}
			free (s);
			CHECK (gp_port_info_list_append (list, info));
		}
		endmntent(mnt);
	}
# else
#  ifdef HAVE_MNTTAB
	FILE *mnt;
	struct mnttab mnttab;
	char	path[1024];
	struct stat stbuf;

	info.type = GP_PORT_DISK;

	mnt = fopen ("/etc/fstab", "r");
	if (mnt) {
		while (! getmntent (mnt, &mntent)) {
			/* detect floppies so we don't access them with the stat() below */
			if (	(NULL != strstr(mnttab.mnt_special,"fd")) ||
				(NULL != strstr(mnttab.mnt_special,"floppy"))
			)
				continue;

			snprintf (path, sizeof(path), "%s/DCIM", mnttab.mnt_mountp);
			if (-1 == stat(path, &stbuf)) {
				snprintf (path, sizeof(path), "%s/dcim", mnttab.mnt_mountp);
				if (-1 == stat(path, &stbuf))
					continue;
			}
			snprintf (info.name, sizeof(info.name), _("Media '%s'"), mntent.mnt_special),
			snprintf (info.path, sizeof(info.path), "disk:%s", mntent.mnt_mountp);
			if (gp_port_info_list_lookup_path (list, info.path) >= GP_OK)
				continue;
			CHECK (gp_port_info_list_append (list, info));
		}
		fclose(mnt);
	}
	mnt = fopen ("/etc/mtab", "r");
	if (mnt) {
		while (! getmntent (mnt, &mntent)) {
			/* detect floppies so we don't access them with the stat() below */
			if (	(NULL != strstr(mnttab.mnt_special,"fd")) ||
				(NULL != strstr(mnttab.mnt_special,"floppy"))
			)
				continue;

			snprintf (path, sizeof(path), "%s/DCIM", mnttab.mnt_mountp);
			if (-1 == stat(path, &stbuf)) {
				snprintf (path, sizeof(path), "%s/dcim", mnttab.mnt_mountp);
				if (-1 == stat(path, &stbuf))
					continue;
			}
			snprintf (info.name, sizeof(info.name), _("Media '%s'"), mntent.mnt_special),
			snprintf (info.path, sizeof(info.path), "disk:%s", mntent.mnt_mountp);
			if (gp_port_info_list_lookup_path (list, info.path) >= GP_OK)
				continue;
			CHECK (gp_port_info_list_append (list, info));
		}
		fclose(mnt);
	}
#  endif
# endif
	/* generic disk:/xxx/ matcher */
	gp_port_info_new (&info);
	gp_port_info_set_type (info, GP_PORT_DISK);
	gp_port_info_set_name (info, "");
	gp_port_info_set_path (info, "^disk:");
	gp_port_info_list_append (list, info); /* do not check return */
	return GP_OK;
}
Ejemplo n.º 8
0
Archivo: unix.c Proyecto: rajbot/gphoto
int
gp_port_library_list (GPPortInfoList *list)
{
	GPPortInfo info;
	char path[1024], prefix[1024];
	int x;
	struct stat s;
#ifdef OS2
	int r, fh, option;
#endif

	/* Copy in the serial port prefix */
	strcpy (prefix, GP_PORT_SERIAL_PREFIX);

	/* On Linux systems, check for devfs */
#ifdef __linux
	if (!stat ("/dev/tts", &s))
		strcpy (prefix, "/dev/tts/%i");
#endif

	for (x=GP_PORT_SERIAL_RANGE_LOW; x<=GP_PORT_SERIAL_RANGE_HIGH; x++) {
		char *xname;

		sprintf (path, prefix, x);

		/* OS/2 seems to need an additional check */
#ifdef OS2
		r = DosOpen (path, &fh, &option, 0, 0, 1,
			     OPEN_FLAGS_FAIL_ON_ERROR |
			     OPEN_SHARE_DENYREADWRITE, 0);
		DosClose(fh);
		if (r)
			continue;
#endif
		/* Very first of all, if the device node is not there,
		 * there is no need to try locking. */
		if ((stat (path, &s) == -1) && ((errno == ENOENT) || (errno == ENODEV)))
			continue;

		gp_port_info_new (&info);
		gp_port_info_set_type (info, GP_PORT_SERIAL);
		xname = malloc (strlen("serial:")+strlen(path)+1);
		strcpy (xname, "serial:");
		strcat (xname, path);
		gp_port_info_set_path (info, xname);
		free (xname);
		xname = malloc (100);
		snprintf (xname, 100, _("Serial Port %i"), x);
		gp_port_info_set_name (info, xname);
		free (xname);
		CHECK (gp_port_info_list_append (list, info));
	}

	/*
	 * Generic support. Append it to the list without checking for
	 * return values, because this entry will not be counted.
	 */
	gp_port_info_new (&info);
	gp_port_info_set_type (info, GP_PORT_SERIAL);
	gp_port_info_set_path (info, "^serial:");
	gp_port_info_set_name (info, "");
	return gp_port_info_list_append (list, info);
}