|
Packit |
713213 |
/*
|
|
Packit |
713213 |
* 1394-Based Digital Camera Control Library
|
|
Packit |
713213 |
*
|
|
Packit |
713213 |
* Written by David Moore <dcm@acm.org>
|
|
Packit |
713213 |
*
|
|
Packit |
713213 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
713213 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
713213 |
* License as published by the Free Software Foundation; either
|
|
Packit |
713213 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
713213 |
*
|
|
Packit |
713213 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
713213 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
713213 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
713213 |
* Lesser General Public License for more details.
|
|
Packit |
713213 |
*
|
|
Packit |
713213 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
713213 |
* License along with this library; if not, write to the Free Software
|
|
Packit |
713213 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
713213 |
*/
|
|
Packit |
713213 |
|
|
Packit |
713213 |
#include <stdio.h>
|
|
Packit |
713213 |
#include <stdlib.h>
|
|
Packit |
713213 |
#include <inttypes.h>
|
|
Packit |
713213 |
#include <string.h>
|
|
Packit |
713213 |
|
|
Packit |
713213 |
#include <dc1394/control.h>
|
|
Packit |
713213 |
#include "internal.h"
|
|
Packit |
713213 |
#include "platform.h"
|
|
Packit |
713213 |
#include "log.h"
|
|
Packit |
713213 |
|
|
Packit |
713213 |
static void
|
|
Packit |
713213 |
destroy_camera_info (camera_info_t * info)
|
|
Packit |
713213 |
{
|
|
Packit |
713213 |
free (info->vendor);
|
|
Packit |
713213 |
free (info->model);
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
static int
|
|
Packit |
713213 |
add_camera (dc1394_t * d, camera_info_t * info)
|
|
Packit |
713213 |
{
|
|
Packit |
713213 |
int n = d->num_cameras;
|
|
Packit |
713213 |
dc1394_log_debug ("Adding camera %"PRIx64":%d %x:%x (%s:%s)",
|
|
Packit |
713213 |
info->guid, info->unit, info->vendor_id, info->model_id,
|
|
Packit |
713213 |
info->vendor, info->model);
|
|
Packit |
713213 |
|
|
Packit |
713213 |
/* For now, exclude duplicate cameras caused by seeing the same camera
|
|
Packit |
713213 |
* on different busses. A better solution is to let the user choose
|
|
Packit |
713213 |
* between these different versions of the same camera, which will require
|
|
Packit |
713213 |
* a new API in the future. */
|
|
Packit |
713213 |
int i;
|
|
Packit |
713213 |
for (i = 0; i < n; i++) {
|
|
Packit |
713213 |
if (d->cameras[i].guid == info->guid
|
|
Packit |
713213 |
&& d->cameras[i].unit == info->unit) {
|
|
Packit |
713213 |
dc1394_log_debug ("Rejected camera %"PRIx64" as duplicate",
|
|
Packit |
713213 |
info->unit);
|
|
Packit |
713213 |
destroy_camera_info (info);
|
|
Packit |
713213 |
return 0;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
d->cameras = realloc (d->cameras, (n + 1) * sizeof (camera_info_t));
|
|
Packit |
713213 |
memcpy (d->cameras + n, info, sizeof (camera_info_t));
|
|
Packit |
713213 |
d->num_cameras = n + 1;
|
|
Packit |
713213 |
return 0;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
static char *
|
|
Packit |
713213 |
parse_leaf (uint32_t offset, uint32_t * quads, int num_quads)
|
|
Packit |
713213 |
{
|
|
Packit |
713213 |
if (offset >= num_quads)
|
|
Packit |
713213 |
return NULL;
|
|
Packit |
713213 |
int num_entries = quads[offset] >> 16;
|
|
Packit |
713213 |
if (offset + num_entries >= num_quads)
|
|
Packit |
713213 |
return NULL;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
uint32_t * dquads = quads + offset + 1;
|
|
Packit |
713213 |
char * str = malloc ((num_entries - 1) * 4 + 1);
|
|
Packit |
713213 |
int i;
|
|
Packit |
713213 |
for (i = 0; i < num_entries - 2; i++) {
|
|
Packit |
713213 |
uint32_t q = dquads[i+2];
|
|
Packit |
713213 |
str[4*i+0] = q >> 24;
|
|
Packit |
713213 |
str[4*i+1] = (q >> 16) & 0xff;
|
|
Packit |
713213 |
str[4*i+2] = (q >> 8) & 0xff;
|
|
Packit |
713213 |
str[4*i+3] = q & 0xff;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
str[4*i] = '\0';
|
|
Packit |
713213 |
return str;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
static int
|
|
Packit |
713213 |
identify_unit (dc1394_t * d, platform_info_t * platform,
|
|
Packit |
713213 |
platform_device_t * dev, uint64_t guid,
|
|
Packit |
713213 |
uint32_t offset, uint32_t * quads, int num_quads, int unit_num,
|
|
Packit |
713213 |
uint32_t vendor_id)
|
|
Packit |
713213 |
{
|
|
Packit |
713213 |
if (offset >= num_quads)
|
|
Packit |
713213 |
return -1;
|
|
Packit |
713213 |
int num_entries = quads[offset] >> 16;
|
|
Packit |
713213 |
if (offset + num_entries >= num_quads)
|
|
Packit |
713213 |
return -1;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
camera_info_t info;
|
|
Packit |
713213 |
memset (&info, 0, sizeof (camera_info_t));
|
|
Packit |
713213 |
|
|
Packit |
713213 |
info.guid = guid;
|
|
Packit |
713213 |
info.unit = unit_num;
|
|
Packit |
713213 |
info.device = dev;
|
|
Packit |
713213 |
info.vendor_id = vendor_id;
|
|
Packit |
713213 |
info.unit_directory = offset;
|
|
Packit |
713213 |
info.platform = platform;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
uint32_t * dquads = quads + offset + 1;
|
|
Packit |
713213 |
int i;
|
|
Packit |
713213 |
for (i = 0; i < num_entries; i++) {
|
|
Packit |
713213 |
uint32_t q = dquads[i];
|
|
Packit |
713213 |
if ((q >> 24) == 0x12)
|
|
Packit |
713213 |
info.unit_spec_ID = q & 0xffffff;
|
|
Packit |
713213 |
if ((q >> 24) == 0x13)
|
|
Packit |
713213 |
info.unit_sw_version = q & 0xffffff;
|
|
Packit |
713213 |
if ((q >> 24) == 0xD4)
|
|
Packit |
713213 |
info.unit_dependent_directory = (q & 0xffffff) + offset + i + 1;
|
|
Packit |
713213 |
if ((q >> 24) == 0x17)
|
|
Packit |
713213 |
info.model_id = q & 0xffffff;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
/*
|
|
Packit |
713213 |
Note on Point Grey (PG) cameras:
|
|
Packit |
713213 |
Although not always advertised, PG cameras are 'sometimes' compatible
|
|
Packit |
713213 |
with IIDC specs. This is especially the case with PG stereo products.
|
|
Packit |
713213 |
The following modifications have been tested with a stereo head
|
|
Packit |
713213 |
(BumbleBee). Most other cameras should be compatible, please consider
|
|
Packit |
713213 |
contributing to the lib if your PG camera is not recognized.
|
|
Packit |
713213 |
|
|
Packit |
713213 |
PG cams sometimes have a Unit_Spec_ID of 0xB09D, instead of the
|
|
Packit |
713213 |
0xA02D of classic IIDC cameras. Also, their software revision differs.
|
|
Packit |
713213 |
I could only get a 1.14 version from my BumbleBee but other versions
|
|
Packit |
713213 |
might exist.
|
|
Packit |
713213 |
|
|
Packit |
713213 |
As PG is regularly providing firmware updates you might also install
|
|
Packit |
713213 |
the latest one in your camera for an increased compatibility.
|
|
Packit |
713213 |
|
|
Packit |
713213 |
Damien
|
|
Packit |
713213 |
|
|
Packit |
713213 |
(updated 2005-04-30)
|
|
Packit |
713213 |
*/
|
|
Packit |
713213 |
|
|
Packit |
713213 |
if ((info.unit_spec_ID != 0xA02D) &&
|
|
Packit |
713213 |
(info.unit_spec_ID != 0xB09D))
|
|
Packit |
713213 |
return -1;
|
|
Packit |
713213 |
if (!info.unit_dependent_directory)
|
|
Packit |
713213 |
return -1;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
if (info.unit_dependent_directory >= num_quads)
|
|
Packit |
713213 |
goto done;
|
|
Packit |
713213 |
num_entries = quads[info.unit_dependent_directory] >> 16;
|
|
Packit |
713213 |
if (info.unit_dependent_directory + num_entries >= num_quads)
|
|
Packit |
713213 |
goto done;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
dquads = quads + info.unit_dependent_directory + 1;
|
|
Packit |
713213 |
for (i = 0; i < num_entries; i++) {
|
|
Packit |
713213 |
uint32_t q = dquads[i];
|
|
Packit |
713213 |
if ((q >> 24) == 0x81)
|
|
Packit |
713213 |
info.vendor = parse_leaf ((q & 0xffffff) +
|
|
Packit |
713213 |
info.unit_dependent_directory + 1 + i,
|
|
Packit |
713213 |
quads, num_quads);
|
|
Packit |
713213 |
if ((q >> 24) == 0x82)
|
|
Packit |
713213 |
info.model = parse_leaf ((q & 0xffffff) +
|
|
Packit |
713213 |
info.unit_dependent_directory + 1 + i,
|
|
Packit |
713213 |
quads, num_quads);
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
done:
|
|
Packit |
713213 |
info.unit_directory = info.unit_directory * 4 + 0x400;
|
|
Packit |
713213 |
info.unit_dependent_directory = info.unit_dependent_directory * 4 + 0x400;
|
|
Packit |
713213 |
return add_camera (d, &info;;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
static int
|
|
Packit |
713213 |
identify_camera (dc1394_t * d, platform_info_t * platform,
|
|
Packit |
713213 |
platform_device_t * dev)
|
|
Packit |
713213 |
{
|
|
Packit |
713213 |
uint64_t guid;
|
|
Packit |
713213 |
uint32_t quads[256];
|
|
Packit |
713213 |
int num_quads = 256;
|
|
Packit |
713213 |
if (platform->dispatch->device_get_config_rom (dev, quads,
|
|
Packit |
713213 |
&num_quads) < 0) {
|
|
Packit |
713213 |
dc1394_log_warning ("Failed to get config ROM from %s device",
|
|
Packit |
713213 |
platform->name);
|
|
Packit |
713213 |
return -1;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
dc1394_log_debug ("Got %d quads of config ROM", num_quads);
|
|
Packit |
713213 |
|
|
Packit |
713213 |
if (num_quads < 7)
|
|
Packit |
713213 |
return -1;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
/* Require 4 quadlets in the bus info block */
|
|
Packit |
713213 |
if ((quads[0] >> 24) != 0x4) {
|
|
Packit |
713213 |
dc1394_log_debug ("Expected 4 quadlets in bus info block, got %d",
|
|
Packit |
713213 |
quads[0] >> 24);
|
|
Packit |
713213 |
return -1;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
/* Require "1394" as the bus identity */
|
|
Packit |
713213 |
if (quads[1] != 0x31333934)
|
|
Packit |
713213 |
return -1;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
guid = ((uint64_t)quads[3] << 32) | quads[4];
|
|
Packit |
713213 |
|
|
Packit |
713213 |
int num_entries = quads[5] >> 16;
|
|
Packit |
713213 |
if (num_quads < num_entries + 6)
|
|
Packit |
713213 |
return -1;
|
|
Packit |
713213 |
int unit = 0;
|
|
Packit |
713213 |
uint32_t vendor_id = 0;
|
|
Packit |
713213 |
int i;
|
|
Packit |
713213 |
for (i = 0; i < num_entries; i++) {
|
|
Packit |
713213 |
uint32_t q = quads[6+i];
|
|
Packit |
713213 |
if ((q >> 24) == 0x03)
|
|
Packit |
713213 |
vendor_id = q & 0xffffff;
|
|
Packit |
713213 |
if ((q >> 24) == 0xD1) {
|
|
Packit |
713213 |
uint32_t offset = (q & 0xffffff) + 6 + i;
|
|
Packit |
713213 |
identify_unit (d, platform, dev, guid, offset, quads, num_quads,
|
|
Packit |
713213 |
unit++, vendor_id);
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
return 0;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
void
|
|
Packit |
713213 |
free_enumeration (dc1394_t * d)
|
|
Packit |
713213 |
{
|
|
Packit |
713213 |
int i;
|
|
Packit |
713213 |
for (i = 0; i < d->num_platforms; i++) {
|
|
Packit |
713213 |
platform_info_t * p = d->platforms + i;
|
|
Packit |
713213 |
if (p->device_list)
|
|
Packit |
713213 |
p->dispatch->free_device_list (p->device_list);
|
|
Packit |
713213 |
p->device_list = NULL;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
for (i = 0; i < d->num_cameras; i++)
|
|
Packit |
713213 |
destroy_camera_info (d->cameras + i);
|
|
Packit |
713213 |
free (d->cameras);
|
|
Packit |
713213 |
d->num_cameras = 0;
|
|
Packit |
713213 |
d->cameras = NULL;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
int
|
|
Packit |
713213 |
refresh_enumeration (dc1394_t * d)
|
|
Packit |
713213 |
{
|
|
Packit |
713213 |
free_enumeration (d);
|
|
Packit |
713213 |
|
|
Packit |
713213 |
dc1394_log_debug ("Enumerating cameras...");
|
|
Packit |
713213 |
int i;
|
|
Packit |
713213 |
for (i = 0; i < d->num_platforms; i++) {
|
|
Packit |
713213 |
platform_info_t * p = d->platforms + i;
|
|
Packit |
713213 |
if (!p->p)
|
|
Packit |
713213 |
continue;
|
|
Packit |
713213 |
dc1394_log_debug("Enumerating platform %s", p->name);
|
|
Packit |
713213 |
p->device_list = p->dispatch->get_device_list (p->p);
|
|
Packit |
713213 |
if (!p->device_list) {
|
|
Packit |
713213 |
dc1394_log_warning("Platform %s failed to get device list",
|
|
Packit |
713213 |
p->name);
|
|
Packit |
713213 |
continue;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
platform_device_t ** list = p->device_list->devices;
|
|
Packit |
713213 |
int j;
|
|
Packit |
713213 |
dc1394_log_debug ("Platform %s has %d device(s)",
|
|
Packit |
713213 |
p->name, p->device_list->num_devices);
|
|
Packit |
713213 |
for (j = 0; j < p->device_list->num_devices; j++)
|
|
Packit |
713213 |
if (identify_camera (d, p, list[j]) < 0)
|
|
Packit |
713213 |
dc1394_log_debug ("Failed to identify %s device %d",
|
|
Packit |
713213 |
p->name, j);
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
return 0;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
dc1394error_t
|
|
Packit |
713213 |
dc1394_camera_enumerate (dc1394_t * d, dc1394camera_list_t **list)
|
|
Packit |
713213 |
{
|
|
Packit |
713213 |
if (refresh_enumeration (d) < 0)
|
|
Packit |
713213 |
return DC1394_FAILURE;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
dc1394camera_list_t * l;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
l = calloc (1, sizeof (dc1394camera_list_t));
|
|
Packit |
713213 |
*list = l;
|
|
Packit |
713213 |
if (d->num_cameras == 0)
|
|
Packit |
713213 |
return DC1394_SUCCESS;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
l->ids = malloc (d->num_cameras * sizeof (dc1394camera_id_t));
|
|
Packit |
713213 |
l->num = 0;
|
|
Packit |
713213 |
|
|
Packit |
713213 |
int i;
|
|
Packit |
713213 |
for (i = 0; i < d->num_cameras; i++) {
|
|
Packit |
713213 |
l->ids[i].guid = d->cameras[i].guid;
|
|
Packit |
713213 |
l->ids[i].unit = d->cameras[i].unit;
|
|
Packit |
713213 |
l->num++;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
return DC1394_SUCCESS;
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|
|
Packit |
713213 |
/*
|
|
Packit |
713213 |
Free a list of cameras returned by dc1394_enumerate_cameras()
|
|
Packit |
713213 |
*/
|
|
Packit |
713213 |
void
|
|
Packit |
713213 |
dc1394_camera_free_list (dc1394camera_list_t *list)
|
|
Packit |
713213 |
{
|
|
Packit |
713213 |
if (list)
|
|
Packit |
713213 |
free (list->ids);
|
|
Packit |
713213 |
list->ids = NULL;
|
|
Packit |
713213 |
free (list);
|
|
Packit |
713213 |
}
|
|
Packit |
713213 |
|