1 /* Aravis - Digital camera library
2  *
3  * Copyright © 2009-2010 Emmanuel Pacaud
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * Author: Emmanuel Pacaud <emmanuel@gnome.org>
21  */
22 
23 /**
24  * SECTION: arvgvinterface
25  * @short_description: GigEVision interface
26  */
27 
28 #include <arpa/inet.h>
29 #include <arvgvinterfaceprivate.h>
30 #include <arvinterfaceprivate.h>
31 #include <arvgvdeviceprivate.h>
32 #include <arvgvcp.h>
33 #include <arvdebug.h>
34 #include <arvmisc.h>
35 #include <arvstr.h>
36 #include <glib/gprintf.h>
37 #include <gio/gio.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <net/if.h>
41 #include <netinet/in.h>
42 #include <netdb.h>
43 #include <ifaddrs.h>
44 #include <stdlib.h>
45 #include <string.h>
46 
47 /* ArvGvDiscoverSocket implementation */
48 
49 typedef struct {
50 	GSocketAddress *interface_address;
51 	GSocket *socket;
52 } ArvGvDiscoverSocket;
53 
54 static gboolean
arv_gv_discover_socket_set_broadcast(ArvGvDiscoverSocket * discover_socket,gboolean enable)55 arv_gv_discover_socket_set_broadcast (ArvGvDiscoverSocket *discover_socket, gboolean enable)
56 {
57 	int socket_fd;
58 	int result;
59 
60 	socket_fd = g_socket_get_fd (discover_socket->socket);
61 
62 	result = setsockopt (socket_fd, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof (enable));
63 
64 	return result == 0;
65 }
66 
67 typedef struct {
68 	unsigned int n_sockets;
69 	GSList *sockets;
70 	GPollFD *poll_fds;
71 } ArvGvDiscoverSocketList;
72 
73 static ArvGvDiscoverSocketList *
arv_gv_discover_socket_list_new(void)74 arv_gv_discover_socket_list_new (void)
75 {
76 	ArvGvDiscoverSocketList *socket_list;
77 	GSList *iter;
78 	struct ifaddrs *ifap  = NULL;
79 	struct ifaddrs *ifap_iter;
80 	int i;
81 
82 	socket_list = g_new0 (ArvGvDiscoverSocketList, 1);
83 
84 	if (getifaddrs (&ifap) < 0)
85 		return socket_list;
86 
87 	for (ifap_iter = ifap; ifap_iter != NULL; ifap_iter = ifap_iter->ifa_next) {
88 		if ((ifap_iter->ifa_flags & IFF_UP) != 0 &&
89 		    (ifap_iter->ifa_flags & IFF_POINTOPOINT) == 0 &&
90 		    (ifap_iter->ifa_addr != NULL) &&
91 		    (ifap_iter->ifa_addr->sa_family == AF_INET)) {
92 			ArvGvDiscoverSocket *discover_socket = g_new0 (ArvGvDiscoverSocket, 1);
93 			GSocketAddress *socket_address;
94 			GInetAddress *inet_address;
95 			char *inet_address_string;
96 			GError *error = NULL;
97 
98 			socket_address = g_socket_address_new_from_native (ifap_iter->ifa_addr,
99 									   sizeof (struct sockaddr));
100 			inet_address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_address));
101 			inet_address_string = g_inet_address_to_string (inet_address);
102 			arv_debug_interface ("[GvDiscoverSocket::new] Add interface %s", inet_address_string);
103 			g_free (inet_address_string);
104 			discover_socket->interface_address = g_inet_socket_address_new (inet_address, 0);
105 			g_object_unref (socket_address);
106 
107 			discover_socket->socket = g_socket_new (G_SOCKET_FAMILY_IPV4,
108 								G_SOCKET_TYPE_DATAGRAM,
109 								G_SOCKET_PROTOCOL_UDP, NULL);
110 			g_socket_bind (discover_socket->socket, discover_socket->interface_address, FALSE, &error);
111 
112 			socket_list->sockets = g_slist_prepend (socket_list->sockets, discover_socket);
113 			socket_list->n_sockets++;
114 		}
115 	}
116 
117 	freeifaddrs (ifap);
118 
119 	socket_list->poll_fds = g_new (GPollFD, socket_list->n_sockets);
120 	for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) {
121 		ArvGvDiscoverSocket *discover_socket = iter->data;
122 
123 		socket_list->poll_fds[i].fd = g_socket_get_fd (discover_socket->socket);
124 		socket_list->poll_fds[i].events =  G_IO_IN;
125 		socket_list->poll_fds[i].revents = 0;
126 	}
127 
128 	return socket_list;
129 }
130 
131 static void
arv_gv_discover_socket_list_free(ArvGvDiscoverSocketList * socket_list)132 arv_gv_discover_socket_list_free (ArvGvDiscoverSocketList *socket_list)
133 {
134 	GSList *iter;
135 
136 	g_return_if_fail (socket_list != NULL);
137 
138 	for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
139 		ArvGvDiscoverSocket *discover_socket = iter->data;
140 
141 		g_object_unref (discover_socket->interface_address);
142 		g_object_unref (discover_socket->socket);
143 		g_free (discover_socket);
144 	}
145 	g_slist_free (socket_list->sockets);
146 	g_free (socket_list->poll_fds);
147 
148 	socket_list->sockets = NULL;
149 	socket_list->n_sockets = 0;
150 	socket_list->poll_fds = NULL;
151 
152 	g_free (socket_list);
153 }
154 
155 static void
arv_gv_discover_socket_list_send_discover_packet(ArvGvDiscoverSocketList * socket_list)156 arv_gv_discover_socket_list_send_discover_packet (ArvGvDiscoverSocketList *socket_list)
157 {
158 	GInetAddress *broadcast_address;
159 	GSocketAddress *broadcast_socket_address;
160 	ArvGvcpPacket *packet;
161 	GSList *iter;
162 	size_t size;
163 
164 	packet = arv_gvcp_packet_new_discovery_cmd (&size);
165 
166 	broadcast_address = g_inet_address_new_from_string ("255.255.255.255");
167 	broadcast_socket_address = g_inet_socket_address_new (broadcast_address, ARV_GVCP_PORT);
168 	g_object_unref (broadcast_address);
169 
170 	for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
171 		ArvGvDiscoverSocket *discover_socket = iter->data;
172 		GError *error = NULL;
173 
174 		arv_gv_discover_socket_set_broadcast (discover_socket, TRUE);
175 		g_socket_send_to (discover_socket->socket,
176 				  broadcast_socket_address,
177 				  (const char *) packet, size,
178 				  NULL, &error);
179 		if (error != NULL) {
180 			arv_warning_interface ("[ArvGVInterface::send_discover_packet] Error: %s", error->message);
181 			g_error_free (error);
182 		}
183 		arv_gv_discover_socket_set_broadcast (discover_socket, FALSE);
184 	}
185 
186 	g_object_unref (broadcast_socket_address);
187 
188 	arv_gvcp_packet_free (packet);
189 }
190 
191 /* ArvGvInterfaceDeviceInfos implementation */
192 
193 typedef struct {
194 	char *name;
195 	char *full_name;
196 	char *user_name;
197 	char *manufacturer;
198 	char *model;
199 	char *serial_number;
200 	char *mac_string;
201 
202 	GInetAddress *interface_address;
203 
204 	guchar discovery_data[ARV_GVBS_DISCOVERY_DATA_SIZE];
205 
206 	volatile gint ref_count;
207 } ArvGvInterfaceDeviceInfos;
208 
209 static ArvGvInterfaceDeviceInfos *
arv_gv_interface_device_infos_new(GInetAddress * interface_address,void * discovery_data)210 arv_gv_interface_device_infos_new (GInetAddress *interface_address,
211 				   void *discovery_data)
212 {
213 	ArvGvInterfaceDeviceInfos *infos;
214 
215 	g_return_val_if_fail (G_IS_INET_ADDRESS (interface_address), NULL);
216 	g_return_val_if_fail (discovery_data != NULL, NULL);
217 
218 	g_object_ref (interface_address);
219 
220 	infos = g_new0 (ArvGvInterfaceDeviceInfos, 1);
221 
222 	memcpy (infos->discovery_data, discovery_data, ARV_GVBS_DISCOVERY_DATA_SIZE);
223 
224 	infos->manufacturer = g_strndup ((char *) &infos->discovery_data[ARV_GVBS_MANUFACTURER_NAME_OFFSET],
225 					 ARV_GVBS_MANUFACTURER_NAME_SIZE);
226 	infos->model = g_strndup ((char *) &infos->discovery_data[ARV_GVBS_MODEL_NAME_OFFSET],
227 				  ARV_GVBS_MODEL_NAME_SIZE);
228 	infos->serial_number = g_strndup ((char *) &infos->discovery_data[ARV_GVBS_SERIAL_NUMBER_OFFSET],
229 					  ARV_GVBS_SERIAL_NUMBER_SIZE);
230 	infos->user_name = g_strndup ((char *) &infos->discovery_data[ARV_GVBS_USER_DEFINED_NAME_OFFSET],
231 				      ARV_GVBS_USER_DEFINED_NAME_SIZE);
232 
233 	infos->name = g_strdup_printf ("%s-%s", arv_vendor_alias_lookup (infos->manufacturer), infos->serial_number);
234 	arv_str_strip (infos->name, ARV_DEVICE_NAME_ILLEGAL_CHARACTERS, ARV_DEVICE_NAME_REPLACEMENT_CHARACTER);
235 	infos->full_name = g_strdup_printf ("%s-%s", infos->manufacturer, infos->serial_number);
236 	arv_str_strip (infos->full_name, ARV_DEVICE_NAME_ILLEGAL_CHARACTERS, ARV_DEVICE_NAME_REPLACEMENT_CHARACTER);
237 
238 	infos->interface_address = interface_address;
239 
240 	infos->mac_string = g_strdup_printf ("%02x:%02x:%02x:%02x:%02x:%02x",
241 					     infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 2],
242 					     infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 3],
243 					     infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 4],
244 					     infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 5],
245 					     infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 6],
246 					     infos->discovery_data[ARV_GVBS_DEVICE_MAC_ADDRESS_HIGH_OFFSET + 7]);
247 	infos->ref_count = 1;
248 
249 	return infos;
250 }
251 
252 static ArvGvInterfaceDeviceInfos *
arv_gv_interface_device_infos_ref(ArvGvInterfaceDeviceInfos * infos)253 arv_gv_interface_device_infos_ref (ArvGvInterfaceDeviceInfos *infos)
254 {
255 	g_return_val_if_fail (infos != NULL, NULL);
256 	g_return_val_if_fail (g_atomic_int_get (&infos->ref_count) > 0, NULL);
257 
258 	g_atomic_int_inc (&infos->ref_count);
259 
260 	return infos;
261 }
262 
263 static void
arv_gv_interface_device_infos_unref(ArvGvInterfaceDeviceInfos * infos)264 arv_gv_interface_device_infos_unref (ArvGvInterfaceDeviceInfos *infos)
265 {
266 	g_return_if_fail (infos != NULL);
267 	g_return_if_fail (g_atomic_int_get (&infos->ref_count) > 0);
268 
269 	if (g_atomic_int_dec_and_test (&infos->ref_count)) {
270 		g_object_unref (infos->interface_address);
271 		g_free (infos->name);
272 		g_free (infos->user_name);
273 		g_free (infos->full_name);
274 		g_free (infos->manufacturer);
275 		g_free (infos->serial_number);
276 		g_free (infos->model);
277 		g_free (infos->mac_string);
278 		g_free (infos);
279 	}
280 }
281 
282 /* ArvGvInterface implementation */
283 
284 static GObjectClass *parent_class = NULL;
285 
286 struct _ArvGvInterfacePrivate {
287 	GHashTable *devices;
288 };
289 
290 static ArvGvInterfaceDeviceInfos *
_discover(GHashTable * devices,const char * device_id)291 _discover (GHashTable *devices, const char *device_id)
292 {
293 	ArvGvDiscoverSocketList *socket_list;
294 	GSList *iter;
295 	char buffer[ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE];
296 	int count;
297 	int i;
298 
299 	g_assert (devices == NULL || device_id == NULL);
300 
301 	if (devices != NULL)
302 		g_hash_table_remove_all (devices);
303 
304 	socket_list = arv_gv_discover_socket_list_new ();
305 
306 	if (socket_list->n_sockets < 1) {
307 		arv_gv_discover_socket_list_free (socket_list);
308 		return NULL;
309 	}
310 
311 	arv_gv_discover_socket_list_send_discover_packet (socket_list);
312 
313 	do {
314 		if (g_poll (socket_list->poll_fds, socket_list->n_sockets, ARV_GV_INTERFACE_DISCOVERY_TIMEOUT_MS) == 0) {
315 			arv_gv_discover_socket_list_free (socket_list);
316 			return NULL;
317 		}
318 
319 		for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) {
320 			ArvGvDiscoverSocket *discover_socket = iter->data;
321 
322 			do {
323 				g_socket_set_blocking (discover_socket->socket, FALSE);
324 				count = g_socket_receive (discover_socket->socket, buffer, ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE,
325 							  NULL, NULL);
326 				g_socket_set_blocking (discover_socket->socket, TRUE);
327 
328 				if (count > 0) {
329 					ArvGvcpPacket *packet = (ArvGvcpPacket *) buffer;
330 
331 					if (g_ntohs (packet->header.command) == ARV_GVCP_COMMAND_DISCOVERY_ACK &&
332 					    g_ntohs (packet->header.id) == 0xffff) {
333 						ArvGvInterfaceDeviceInfos *device_infos;
334 						GInetAddress *interface_address;
335 						char *address_string;
336 						char *data = buffer + sizeof (ArvGvcpHeader);
337 
338 						arv_gvcp_packet_debug (packet, ARV_DEBUG_LEVEL_LOG);
339 
340 						interface_address = g_inet_socket_address_get_address
341 							(G_INET_SOCKET_ADDRESS (discover_socket->interface_address));
342 						device_infos = arv_gv_interface_device_infos_new (interface_address,
343 												  data);
344 						address_string = g_inet_address_to_string (interface_address);
345 
346 						arv_debug_interface ("[GvInterface::discovery] Device '%s' found "
347 								     "(interface %s) user_name '%s' - MAC_name '%s'",
348 								     device_infos->name,
349 								     address_string,
350 								     device_infos->user_name,
351 								     device_infos->full_name,
352 								     device_infos->mac_string);
353 
354 						g_free (address_string);
355 
356 						if (devices != NULL) {
357 							if (device_infos->name != NULL && device_infos->name[0] != '\0')
358 								g_hash_table_replace (devices, device_infos->name,
359 										      arv_gv_interface_device_infos_ref (device_infos));
360 							if (device_infos->full_name != NULL && device_infos->full_name[0] != '\0')
361 								g_hash_table_replace (devices, device_infos->full_name,
362 										      arv_gv_interface_device_infos_ref (device_infos));
363 							if (device_infos->user_name != NULL && device_infos->user_name[0] != '\0')
364 								g_hash_table_replace (devices, device_infos->user_name,
365 										      arv_gv_interface_device_infos_ref (device_infos));
366 							g_hash_table_replace (devices, device_infos->mac_string,
367 									      arv_gv_interface_device_infos_ref (device_infos));
368 						} else {
369 							if (device_id == NULL ||
370 							    g_strcmp0 (device_infos->name, device_id) == 0 ||
371 							    g_strcmp0 (device_infos->full_name, device_id) == 0 ||
372 							    g_strcmp0 (device_infos->user_name, device_id) == 0 ||
373 							    g_strcmp0 (device_infos->mac_string, device_id) == 0) {
374 								arv_gv_discover_socket_list_free (socket_list);
375 
376 								return device_infos;
377 							}
378 						}
379 
380 						arv_gv_interface_device_infos_unref (device_infos);
381 					}
382 				}
383 			} while (count > 0);
384 		}
385 	} while (1);
386 }
387 
388 static void
arv_gv_interface_discover(ArvGvInterface * gv_interface)389 arv_gv_interface_discover (ArvGvInterface *gv_interface)
390 {
391 	_discover (gv_interface->priv->devices, NULL);
392 }
393 
394 static GInetAddress *
_device_infos_to_ginetaddress(ArvGvInterfaceDeviceInfos * device_infos)395 _device_infos_to_ginetaddress (ArvGvInterfaceDeviceInfos *device_infos)
396 {
397 	GInetAddress *device_address;
398 
399 	device_address = g_inet_address_new_from_bytes
400 		(&device_infos->discovery_data[ARV_GVBS_CURRENT_IP_ADDRESS_OFFSET],
401 		 G_SOCKET_FAMILY_IPV4);
402 
403 	return device_address;
404 }
405 
406 static void
arv_gv_interface_update_device_list(ArvInterface * interface,GArray * device_ids)407 arv_gv_interface_update_device_list (ArvInterface *interface, GArray *device_ids)
408 {
409 	ArvGvInterface *gv_interface;
410 	GHashTableIter iter;
411 	gpointer key, value;
412 
413 	g_assert (device_ids->len == 0);
414 
415 	gv_interface = ARV_GV_INTERFACE (interface);
416 
417 	arv_gv_interface_discover (gv_interface);
418 
419 	g_hash_table_iter_init (&iter, gv_interface->priv->devices);
420 	while (g_hash_table_iter_next (&iter, &key, &value)) {
421 		ArvGvInterfaceDeviceInfos *infos = value;
422 
423 		if (g_strcmp0 (key, infos->name) == 0) {
424 			ArvInterfaceDeviceIds *ids;
425 			GInetAddress *device_address;
426 
427 			ids = g_new0 (ArvInterfaceDeviceIds, 1);
428 
429 			ids->device = g_strdup (key);
430 			ids->physical = g_strdup (infos->mac_string);
431 			device_address = _device_infos_to_ginetaddress (infos);
432 			ids->address = g_inet_address_to_string (device_address);
433 			g_object_unref (device_address);
434 			ids->vendor = g_strdup (infos->manufacturer);
435 			ids->model = g_strdup (infos->model);
436 			ids->serial_nbr = g_strdup (infos->serial_number);
437 
438 			g_array_append_val (device_ids, ids);
439 		}
440 	}
441 }
442 
443 static GInetAddress *
arv_gv_interface_camera_locate(ArvGvInterface * gv_interface,GInetAddress * device_address)444 arv_gv_interface_camera_locate (ArvGvInterface *gv_interface, GInetAddress *device_address)
445 {
446 	ArvGvDiscoverSocketList *socket_list;
447 	ArvGvcpPacket *packet;
448 	char buffer[ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE];
449 	GSList *iter;
450 	GSocketAddress *device_socket_address;
451 	size_t size;
452 	int i, count;
453 
454 	socket_list = arv_gv_discover_socket_list_new ();
455 
456 	if (socket_list->n_sockets < 1) {
457 		arv_gv_discover_socket_list_free (socket_list);
458 		return NULL;
459 	}
460 
461 	/* Just read a random register from the camera socket */
462 	packet = arv_gvcp_packet_new_read_register_cmd (ARV_GVBS_N_STREAM_CHANNELS_OFFSET, 0, &size);
463 	device_socket_address = g_inet_socket_address_new (device_address, ARV_GVCP_PORT);
464 
465 	for (iter = socket_list->sockets; iter != NULL; iter = iter->next) {
466 		ArvGvDiscoverSocket *socket = iter->data;
467 		GError *error = NULL;
468 
469 		g_socket_send_to (socket->socket,
470 				device_socket_address,
471 				(const char *) packet, size,
472 				NULL, &error);
473 		if (error != NULL) {
474 			arv_warning_interface ("[ArvGVInterface::arv_gv_interface_camera_locate] Error: %s", error->message);
475 			g_error_free (error);
476 		}
477 	}
478 
479 	arv_gvcp_packet_free (packet);
480 
481 	do {
482 		/* Now parse the result */
483 		if (g_poll (socket_list->poll_fds, socket_list->n_sockets,
484 					ARV_GV_INTERFACE_DISCOVERY_TIMEOUT_MS) == 0) {
485 			arv_gv_discover_socket_list_free (socket_list);
486 			return NULL;
487 		}
488 
489 		for (i = 0, iter = socket_list->sockets; iter != NULL; i++, iter = iter->next) {
490 			ArvGvDiscoverSocket *socket = iter->data;
491 
492 			do {
493 				g_socket_set_blocking (socket->socket, FALSE);
494 				count = g_socket_receive (socket->socket, buffer,
495 						ARV_GV_INTERFACE_SOCKET_BUFFER_SIZE,
496 						NULL, NULL);
497 				g_socket_set_blocking (socket->socket, TRUE);
498 
499 				if (count > 0) {
500 					ArvGvcpPacket *packet = (ArvGvcpPacket *) buffer;
501 
502 					if (g_ntohs (packet->header.command) == ARV_GVCP_COMMAND_READ_REGISTER_CMD ||
503 							g_ntohs (packet->header.command) == ARV_GVCP_COMMAND_READ_REGISTER_ACK) {
504 						GInetAddress *interface_address = g_inet_socket_address_get_address(
505 								G_INET_SOCKET_ADDRESS (socket->interface_address));
506 
507 						g_object_ref(interface_address);
508 						arv_gv_discover_socket_list_free (socket_list);
509 						return interface_address;
510 					}
511 				}
512 			} while (count > 0);
513 		}
514 	} while (1);
515 	arv_gv_discover_socket_list_free (socket_list);
516 	return NULL;
517 }
518 
519 static ArvDevice *
_open_device(ArvInterface * interface,GHashTable * devices,const char * device_id)520 _open_device (ArvInterface *interface, GHashTable *devices, const char *device_id)
521 {
522 	ArvGvInterface *gv_interface;
523 	ArvDevice *device = NULL;
524 	ArvGvInterfaceDeviceInfos *device_infos;
525 	GInetAddress *device_address;
526 
527 	gv_interface = ARV_GV_INTERFACE (interface);
528 
529 	if (device_id == NULL) {
530 		GList *device_list;
531 
532 		device_list = g_hash_table_get_values (devices);
533 		device_infos = device_list != NULL ? device_list->data : NULL;
534 		g_list_free (device_list);
535 	} else
536 		device_infos = g_hash_table_lookup (devices, device_id);
537 
538 	if (device_infos == NULL) {
539 		struct addrinfo hints;
540 		struct addrinfo *servinfo, *endpoint;
541 
542 		if (device_id == NULL)
543 			return NULL;
544 
545 		/* Try if device_id is a hostname/IP address */
546 
547 		memset(&hints, 0, sizeof (hints));
548 		hints.ai_family = AF_INET;
549 		hints.ai_socktype = SOCK_DGRAM;
550 
551 		if (getaddrinfo(device_id, "3956", &hints, &servinfo) != 0) {
552 			return NULL;
553 		}
554 
555 		for (endpoint=servinfo; endpoint!=NULL; endpoint=endpoint->ai_next) {
556 			char ipstr[INET_ADDRSTRLEN];
557 			struct sockaddr_in *ip = (struct sockaddr_in *) endpoint->ai_addr;
558 
559 			inet_ntop (endpoint->ai_family, &ip->sin_addr, ipstr, sizeof (ipstr));
560 
561 			device_address = g_inet_address_new_from_string (ipstr);
562 			if (device_address != NULL) {
563 				/* Try and find an interface that the camera will respond on */
564 				GInetAddress *interface_address =
565 					arv_gv_interface_camera_locate (gv_interface, device_address);
566 
567 				if (interface_address != NULL) {
568 					device = arv_gv_device_new (interface_address, device_address);
569 					g_object_unref (interface_address);
570 				}
571 			}
572 			g_object_unref (device_address);
573 			if (device != NULL) {
574 				break;
575 			}
576 		}
577 		freeaddrinfo (servinfo);
578 		return device;
579 	}
580 
581 	device_address = _device_infos_to_ginetaddress (device_infos);
582 	device = arv_gv_device_new (device_infos->interface_address, device_address);
583 	g_object_unref (device_address);
584 
585 	return device;
586 }
587 
588 static ArvDevice *
arv_gv_interface_open_device(ArvInterface * interface,const char * device_id)589 arv_gv_interface_open_device (ArvInterface *interface, const char *device_id)
590 {
591 	ArvDevice *device;
592 	ArvGvInterfaceDeviceInfos *device_infos;
593 
594 	device = _open_device (interface, ARV_GV_INTERFACE (interface)->priv->devices, device_id);
595 	if (ARV_IS_DEVICE (device))
596 		return device;
597 
598 	device_infos = _discover (NULL, device_id);
599 	if (device_infos != NULL) {
600 		GInetAddress *device_address;
601 
602 		device_address = _device_infos_to_ginetaddress (device_infos);
603 		device = arv_gv_device_new (device_infos->interface_address, device_address);
604 		g_object_unref (device_address);
605 
606 		arv_gv_interface_device_infos_unref (device_infos);
607 
608 		return device;
609 	}
610 
611 	return NULL;
612 }
613 
614 static ArvInterface *gv_interface = NULL;
615 ARV_DEFINE_STATIC_MUTEX (gv_interface_mutex);
616 
617 /**
618  * arv_gv_interface_get_instance:
619  *
620  * Gets the unique instance of the GV interface.
621  *
622  * Returns: (transfer none): a #ArvInterface singleton.
623  */
624 
625 ArvInterface *
arv_gv_interface_get_instance(void)626 arv_gv_interface_get_instance (void)
627 {
628 	arv_g_mutex_lock (&gv_interface_mutex);
629 
630 	if (gv_interface == NULL)
631 		gv_interface = g_object_new (ARV_TYPE_GV_INTERFACE, NULL);
632 
633 	arv_g_mutex_unlock (&gv_interface_mutex);
634 
635 	return ARV_INTERFACE (gv_interface);
636 }
637 
638 void
arv_gv_interface_destroy_instance(void)639 arv_gv_interface_destroy_instance (void)
640 {
641 	arv_g_mutex_lock (&gv_interface_mutex);
642 
643 	if (gv_interface != NULL) {
644 		g_object_unref (gv_interface);
645 		gv_interface = NULL;
646 	}
647 
648 	arv_g_mutex_unlock (&gv_interface_mutex);
649 }
650 
651 static void
arv_gv_interface_init(ArvGvInterface * gv_interface)652 arv_gv_interface_init (ArvGvInterface *gv_interface)
653 {
654 	gv_interface->priv = G_TYPE_INSTANCE_GET_PRIVATE (gv_interface, ARV_TYPE_GV_INTERFACE, ArvGvInterfacePrivate);
655 
656 	gv_interface->priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
657 							     (GDestroyNotify) arv_gv_interface_device_infos_unref);
658 }
659 
660 static void
arv_gv_interface_finalize(GObject * object)661 arv_gv_interface_finalize (GObject *object)
662 {
663 	ArvGvInterface *gv_interface = ARV_GV_INTERFACE (object);
664 
665 	g_hash_table_unref (gv_interface->priv->devices);
666 	gv_interface->priv->devices = NULL;
667 
668 	parent_class->finalize (object);
669 }
670 
671 static void
arv_gv_interface_class_init(ArvGvInterfaceClass * gv_interface_class)672 arv_gv_interface_class_init (ArvGvInterfaceClass *gv_interface_class)
673 {
674 	GObjectClass *object_class = G_OBJECT_CLASS (gv_interface_class);
675 	ArvInterfaceClass *interface_class = ARV_INTERFACE_CLASS (gv_interface_class);
676 
677 	g_type_class_add_private (gv_interface_class, sizeof (ArvGvInterfacePrivate));
678 
679 	parent_class = g_type_class_peek_parent (gv_interface_class);
680 
681 	object_class->finalize = arv_gv_interface_finalize;
682 
683 	interface_class->update_device_list = arv_gv_interface_update_device_list;
684 	interface_class->open_device = arv_gv_interface_open_device;
685 
686 	interface_class->protocol = "GigEVision";
687 }
688 
689 G_DEFINE_TYPE (ArvGvInterface, arv_gv_interface, ARV_TYPE_INTERFACE)
690