diff options
author | Marcus Meissner <marcus@jet.franken.de> | 2006-02-16 22:38:47 +0000 |
---|---|---|
committer | Marcus Meissner <marcus@jet.franken.de> | 2006-02-16 22:38:47 +0000 |
commit | 2e594cd9604ceef88fde92a7f64e21ce3a1b395e (patch) | |
tree | 076e57e52674995f25f00ae661d9474655407730 /libgphoto2_port/ptpip | |
parent | 0a26542bec019c664c3afd6c92dc8f8693b95ebc (diff) | |
download | libgphoto2-2e594cd9604ceef88fde92a7f64e21ce3a1b395e.tar.gz |
Added PTPIP port support.
Added Bonjour / mDNSResponder style multicast DNS queries for cameras.
git-svn-id: https://svn.code.sf.net/p/gphoto/code/trunk/libgphoto2@8552 67ed7778-7388-44ab-90cf-0a291f65f57c
Diffstat (limited to 'libgphoto2_port/ptpip')
-rw-r--r-- | libgphoto2_port/ptpip/.cvsignore | 6 | ||||
-rw-r--r-- | libgphoto2_port/ptpip/Makefile.am | 13 | ||||
-rw-r--r-- | libgphoto2_port/ptpip/ptpip.c | 256 |
3 files changed, 275 insertions, 0 deletions
diff --git a/libgphoto2_port/ptpip/.cvsignore b/libgphoto2_port/ptpip/.cvsignore new file mode 100644 index 000000000..0839b71df --- /dev/null +++ b/libgphoto2_port/ptpip/.cvsignore @@ -0,0 +1,6 @@ +*.la +*.lo +.libs +.deps +Makefile +Makefile.in diff --git a/libgphoto2_port/ptpip/Makefile.am b/libgphoto2_port/ptpip/Makefile.am new file mode 100644 index 000000000..e1d10dec3 --- /dev/null +++ b/libgphoto2_port/ptpip/Makefile.am @@ -0,0 +1,13 @@ +EXTRA_DIST = + +iolib_LTLIBRARIES = ptpip.la + +ptpip_la_LDFLAGS = -module -no-undefined -avoid-version \ + -export-dynamic \ + -export-symbols $(top_srcdir)/iolib.sym +ptpip_la_CPPFLAGS = \ + -I$(top_srcdir)/libgphoto2_port $(INTL_CFLAGS) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(LIBUSB_CFLAGS) $(HAL_CFLAGS) +ptpip_la_DEPENDENCIES = $(top_srcdir)/iolib.sym +ptpip_la_LIBADD = $(top_builddir)/libgphoto2_port/libgphoto2_port.la @MDNS_LIBS@ +ptpip_la_SOURCES = ptpip.c diff --git a/libgphoto2_port/ptpip/ptpip.c b/libgphoto2_port/ptpip/ptpip.c new file mode 100644 index 000000000..7668269be --- /dev/null +++ b/libgphoto2_port/ptpip/ptpip.c @@ -0,0 +1,256 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* ptpip.c + * + * Copyright (c) 2006 Marcus Meissner <marcus@jet.franken.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" +#include <gphoto2-port-library.h> + +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/param.h> +#include <string.h> + +#include <gphoto2-port.h> +#include <gphoto2-port-result.h> +#include <gphoto2-port-log.h> + +#ifdef ENABLE_NLS +# include <libintl.h> +# undef _ +# define _(String) dgettext (GETTEXT_PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define N_(String) (String) +#endif + +#define CHECK(result) {int r=(result); if (r<0) return (r);} + +struct _GPPortPrivateLibrary { +}; + +GPPortType +gp_port_library_type (void) +{ + return GP_PORT_PTPIP; +} + +#ifdef HAVE_MDNS_BONJOUR + +#include <netinet/in.h> +#include <dns_sd.h> +#include <netdb.h> +#include <arpa/inet.h> + +struct mdnsinfo +{ + GPPortInfoList* list; + const char* name; +}; + +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; + + 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); + info.type = GP_PORT_PTPIP; + snprintf (info.name, sizeof(info.name), mdnsi->name); + snprintf (info.path, sizeof(info.path), "ptpip:%s", inet_ntoa(inaddr)); + gp_port_info_list_append (mdnsi->list, info); +} + +static void +_ptpip_enumerate ( + DNSServiceRef sdRef, DNSServiceFlags flags, + uint32_t interfaceIndex, DNSServiceErrorType errorCode, + const char *serviceName, const char *regtype, const char *replyDomain, + void *context +) { + struct mdnsinfo mdnsi; + DNSServiceRef sd; + + if (errorCode != kDNSServiceErr_NoError) { + gp_log (GP_LOG_ERROR, "ptpip", "Error on _ptp._tcp query."); + return; + } + gp_log (GP_LOG_DEBUG, "ptpip", "found %s, %s, %s", serviceName, regtype, replyDomain); + mdnsi.list = context; + mdnsi.name = serviceName; + DNSServiceResolve (&sd, + 0, + interfaceIndex, + serviceName, + regtype, + replyDomain, + _ptpip_resolved, + &mdnsi + ); + DNSServiceProcessResult (sd); + DNSServiceRefDeallocate (sd); +} +#endif + +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 + + info.type = GP_PORT_PTPIP; + snprintf (info.name, sizeof(info.name), _("PTP/IP Connection")); + snprintf (info.path, sizeof(info.path), "ptpip:"); + CHECK (gp_port_info_list_append (list, info)); + + /* Generic matcher so you can pass any IP address */ + memset (info.name, 0, sizeof(info.name)); + snprintf (info.path, sizeof(info.path), "^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); + 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; +} + +static int gp_port_ptpip_init (GPPort *dev) +{ + dev->pl = malloc (sizeof (GPPortPrivateLibrary)); + if (!dev->pl) + return GP_ERROR_NO_MEMORY; + memset (dev->pl, 0, sizeof(GPPortPrivateLibrary)); + return GP_OK; +} + +static int +gp_port_ptpip_exit (GPPort *port) +{ + if (port->pl) { + free (port->pl); + port->pl = NULL; + } + + return GP_OK; +} + +static int +gp_port_ptpip_open (GPPort *port) +{ + return GP_OK; +} + +static int +gp_port_ptpip_close (GPPort *port) +{ + return GP_OK; +} + +static int +gp_port_ptpip_write (GPPort *port, const char *bytes, int size) +{ + return GP_OK; +} + +static int +gp_port_ptpip_read(GPPort *port, char *bytes, int size) +{ + return GP_OK; +} + +GPPortOperations * +gp_port_library_operations (void) +{ + GPPortOperations *ops; + + ops = malloc (sizeof (GPPortOperations)); + if (!ops) + return NULL; + memset (ops, 0, sizeof (GPPortOperations)); + ops->init = gp_port_ptpip_init; + ops->exit = gp_port_ptpip_exit; + ops->open = gp_port_ptpip_open; + ops->close = gp_port_ptpip_close; + ops->read = gp_port_ptpip_read; + ops->write = gp_port_ptpip_write; + return ops; +} |