Blame dc1394/enumeration.c

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