Blame dc1394/juju/control.c

Packit 713213
/*
Packit 713213
 * 1394-Based Digital Camera Control Library
Packit 713213
 *
Packit 713213
 * Juju backend for dc1394
Packit 713213
 * 
Packit 713213
 * Written by Kristian Hoegsberg <krh@bitplanet.net>
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 <errno.h>
Packit 713213
#include <unistd.h>
Packit 713213
#include <string.h>
Packit 713213
#include <dirent.h>
Packit 713213
#include <fcntl.h>
Packit 713213
#include <sys/ioctl.h>
Packit 713213
#include <inttypes.h>
Packit 713213
#include <arpa/inet.h>
Packit 713213
Packit 713213
#include "config.h"
Packit 713213
#include "platform.h"
Packit 713213
#include "internal.h"
Packit 713213
#include "juju.h"
Packit 713213
Packit 713213
#define ptr_to_u64(p) ((__u64)(unsigned long)(p))
Packit 713213
#define u64_to_ptr(p) ((void *)(unsigned long)(p))
Packit 713213
Packit 713213
Packit 713213
static platform_t *
Packit 713213
dc1394_juju_new (void)
Packit 713213
{
Packit 713213
    DIR * dir;
Packit 713213
    struct dirent * de;
Packit 713213
    int num_devices = 0;
Packit 713213
Packit 713213
    dir = opendir("/dev");
Packit 713213
    if (!dir) {
Packit 713213
        dc1394_log_error("Failed to create juju: opendir: %m");
Packit 713213
        return NULL;
Packit 713213
    }
Packit 713213
    while ((de = readdir(dir))) {
Packit 713213
        if (strncmp(de->d_name, "fw", 2) != 0)
Packit 713213
            continue;
Packit 713213
        dc1394_log_debug("Juju: Found /dev/%s", de->d_name);
Packit 713213
        num_devices++;
Packit 713213
    }
Packit 713213
    closedir(dir);
Packit 713213
Packit 713213
    if (num_devices == 0) {
Packit 713213
        dc1394_log_debug("Juju: Found no devices /dev/fw*");
Packit 713213
        return NULL;
Packit 713213
    }
Packit 713213
Packit 713213
    platform_t * p = calloc (1, sizeof (platform_t));
Packit 713213
    return p;
Packit 713213
}
Packit 713213
static void
Packit 713213
dc1394_juju_free (platform_t * p)
Packit 713213
{
Packit 713213
    free (p);
Packit 713213
}
Packit 713213
Packit 713213
struct _platform_device_t {
Packit 713213
    uint32_t config_rom[256];
Packit 713213
    char filename[32];
Packit 713213
};
Packit 713213
Packit 713213
static platform_device_list_t *
Packit 713213
dc1394_juju_get_device_list (platform_t * p)
Packit 713213
{
Packit 713213
    DIR * dir;
Packit 713213
    struct dirent * de;
Packit 713213
    platform_device_list_t * list;
Packit 713213
    uint32_t allocated_size = 64;
Packit 713213
Packit 713213
    list = calloc (1, sizeof (platform_device_list_t));
Packit 713213
    if (!list)
Packit 713213
        return NULL;
Packit 713213
    list->devices = malloc(allocated_size * sizeof(platform_device_t *));
Packit 713213
    if (!list->devices) {
Packit 713213
        free (list);
Packit 713213
        return NULL;
Packit 713213
    }
Packit 713213
Packit 713213
    dir = opendir("/dev");
Packit 713213
    if (dir == NULL) {
Packit 713213
        dc1394_log_error("opendir: %m");
Packit 713213
        free (list->devices);
Packit 713213
        free (list);
Packit 713213
        return NULL;
Packit 713213
    }
Packit 713213
Packit 713213
    while ((de = readdir(dir))) {
Packit 713213
        char filename[32];
Packit 713213
        int fd;
Packit 713213
        platform_device_t * device;
Packit 713213
        struct fw_cdev_get_info get_info;
Packit 713213
        struct fw_cdev_event_bus_reset reset;
Packit 713213
Packit 713213
        if (strncmp(de->d_name, "fw", 2) != 0 ||
Packit 713213
                de->d_name[2] < '0' || de->d_name[2] > '9')
Packit 713213
            continue;
Packit 713213
Packit 713213
        snprintf(filename, sizeof filename, "/dev/%s", de->d_name);
Packit 713213
        fd = open(filename, O_RDWR);
Packit 713213
        if (fd < 0) {
Packit 713213
            dc1394_log_debug("Juju: Failed to open %s: %s", filename,
Packit 713213
                    strerror (errno));
Packit 713213
            continue;
Packit 713213
        }
Packit 713213
        dc1394_log_debug("Juju: Opened %s successfully", filename);
Packit 713213
Packit 713213
        device = malloc (sizeof (platform_device_t));
Packit 713213
        if (!device) {
Packit 713213
            close (fd);
Packit 713213
            continue;
Packit 713213
        }
Packit 713213
Packit 713213
        get_info.version = FW_CDEV_VERSION;
Packit 713213
        get_info.rom = ptr_to_u64(&device->config_rom);
Packit 713213
        get_info.rom_length = 1024;
Packit 713213
        get_info.bus_reset = ptr_to_u64(&reset);
Packit 713213
        if (ioctl(fd, FW_CDEV_IOC_GET_INFO, &get_info) < 0) {
Packit 713213
            dc1394_log_error("GET_CONFIG_ROM failed for %s: %m",filename);
Packit 713213
            free (device);
Packit 713213
            close(fd);
Packit 713213
            continue;
Packit 713213
        }
Packit 713213
        close (fd);
Packit 713213
Packit 713213
        strcpy (device->filename, filename);
Packit 713213
        list->devices[list->num_devices] = device;
Packit 713213
        list->num_devices++;
Packit 713213
Packit 713213
        if (list->num_devices >= allocated_size) {
Packit 713213
            allocated_size += 64;
Packit 713213
            list->devices = realloc (list->devices, allocated_size * sizeof (platform_device_t *));
Packit 713213
            if (!list->devices)
Packit 713213
                return NULL;
Packit 713213
        }
Packit 713213
    }
Packit 713213
    closedir(dir);
Packit 713213
Packit 713213
    return list;
Packit 713213
}
Packit 713213
Packit 713213
static void
Packit 713213
dc1394_juju_free_device_list (platform_device_list_t * d)
Packit 713213
{
Packit 713213
    int i;
Packit 713213
    for (i = 0; i < d->num_devices; i++)
Packit 713213
        free (d->devices[i]);
Packit 713213
    free (d->devices);
Packit 713213
    free (d);
Packit 713213
}
Packit 713213
Packit 713213
static int
Packit 713213
dc1394_juju_device_get_config_rom (platform_device_t * device,
Packit 713213
                                uint32_t * quads, int * num_quads)
Packit 713213
{
Packit 713213
    if (*num_quads > 256)
Packit 713213
        *num_quads = 256;
Packit 713213
Packit 713213
    memcpy (quads, device->config_rom, *num_quads * sizeof (uint32_t));
Packit 713213
    return 0;
Packit 713213
}
Packit 713213
Packit 713213
static juju_iso_info *
Packit 713213
add_iso_resource (platform_camera_t *cam)
Packit 713213
{
Packit 713213
    juju_iso_info *res = calloc (1, sizeof (juju_iso_info));
Packit 713213
    if (!res)
Packit 713213
        return NULL;
Packit 713213
    res->next = cam->iso_resources;
Packit 713213
    cam->iso_resources = res;
Packit 713213
    return res;
Packit 713213
}
Packit 713213
Packit 713213
static void
Packit 713213
remove_iso_resource (platform_camera_t *cam, juju_iso_info * res)
Packit 713213
{
Packit 713213
    juju_iso_info **ptr = &cam->iso_resources;
Packit 713213
    while (*ptr) {
Packit 713213
        if (*ptr == res) {
Packit 713213
            *ptr = res->next;
Packit 713213
            free (res);
Packit 713213
            return;
Packit 713213
        }
Packit 713213
        ptr = &(*ptr)->next;
Packit 713213
    }
Packit 713213
}
Packit 713213
Packit 713213
static platform_camera_t *
Packit 713213
dc1394_juju_camera_new (platform_t * p, platform_device_t * device, uint32_t unit_directory_offset)
Packit 713213
{
Packit 713213
    int fd;
Packit 713213
    platform_camera_t * camera;
Packit 713213
    struct fw_cdev_get_info get_info;
Packit 713213
    struct fw_cdev_event_bus_reset reset;
Packit 713213
Packit 713213
    fd = open(device->filename, O_RDWR);
Packit 713213
    if (fd < 0) {
Packit 713213
        dc1394_log_error("could not open device %s: %m", device->filename);
Packit 713213
        return NULL;
Packit 713213
    }
Packit 713213
Packit 713213
    get_info.version = FW_CDEV_VERSION;
Packit 713213
    get_info.rom = 0;
Packit 713213
    get_info.rom_length = 0;
Packit 713213
    get_info.bus_reset = ptr_to_u64(&reset);
Packit 713213
    if (ioctl(fd, FW_CDEV_IOC_GET_INFO, &get_info) < 0) {
Packit 713213
        dc1394_log_error("IOC_GET_INFO failed for a device %s: %m",device->filename);
Packit 713213
        close(fd);
Packit 713213
        return NULL;
Packit 713213
    }
Packit 713213
Packit 713213
    dc1394_log_debug("Juju: kernel API has version %d", get_info.version);
Packit 713213
Packit 713213
    camera = calloc (1, sizeof (platform_camera_t));
Packit 713213
    camera->fd = fd;
Packit 713213
    camera->generation = reset.generation;
Packit 713213
    camera->node_id = reset.node_id;
Packit 713213
    strcpy (camera->filename, device->filename);
Packit 713213
Packit 713213
    camera->header_size = 4;
Packit 713213
    if (get_info.version >= 2)
Packit 713213
        camera->header_size = 8;
Packit 713213
Packit 713213
    camera->kernel_abi_version=get_info.version;
Packit 713213
Packit 713213
    return camera;
Packit 713213
}
Packit 713213
Packit 713213
static void dc1394_juju_camera_free (platform_camera_t * cam)
Packit 713213
{
Packit 713213
    while (cam->iso_resources)
Packit 713213
        remove_iso_resource (cam, cam->iso_resources);
Packit 713213
    close (cam->fd);
Packit 713213
    free (cam);
Packit 713213
}
Packit 713213
Packit 713213
static void
Packit 713213
dc1394_juju_camera_set_parent (platform_camera_t * cam, dc1394camera_t * parent)
Packit 713213
{
Packit 713213
    cam->camera = parent;
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_camera_print_info (platform_camera_t * camera, FILE *fd)
Packit 713213
{
Packit 713213
    fprintf(fd,"------ Camera platform-specific information ------\n");
Packit 713213
    fprintf(fd,"Device filename                   :     %s\n", camera->filename);
Packit 713213
    return DC1394_SUCCESS;
Packit 713213
}
Packit 713213
Packit 713213
#define MIN(a,b) ((a) < (b) ? (a) : (b))
Packit 713213
Packit 713213
typedef struct _juju_response_info {
Packit 713213
    int got_response;
Packit 713213
    uint32_t rcode;
Packit 713213
    uint32_t *data;
Packit 713213
    int num_quads;
Packit 713213
    int actual_num_quads;
Packit 713213
} juju_response_info;
Packit 713213
Packit 713213
static int
Packit 713213
juju_handle_event (platform_camera_t * cam)
Packit 713213
{
Packit 713213
    union {
Packit 713213
        struct {
Packit 713213
            struct fw_cdev_event_response r;
Packit 713213
            __u32 buffer[cam->max_response_quads];
Packit 713213
        } response;
Packit 713213
        struct fw_cdev_event_bus_reset reset;
Packit 713213
        struct fw_cdev_event_iso_resource resource;
Packit 713213
    } u;
Packit 713213
    int len, i;
Packit 713213
    juju_response_info *resp_info;
Packit 713213
    juju_iso_info *iso_info;
Packit 713213
Packit 713213
    len = read (cam->fd, &u, sizeof u);
Packit 713213
    if (len < 0) {
Packit 713213
        dc1394_log_error("juju: Read failed: %m");
Packit 713213
        return -1;
Packit 713213
    }
Packit 713213
Packit 713213
    switch (u.reset.type) {
Packit 713213
    case FW_CDEV_EVENT_BUS_RESET:
Packit 713213
        cam->generation = u.reset.generation;
Packit 713213
        cam->node_id = u.reset.node_id;
Packit 713213
        dc1394_log_debug ("juju: Bus reset, gen %d, node 0x%x",
Packit 713213
                cam->generation, cam->node_id);
Packit 713213
        break;
Packit 713213
Packit 713213
    case FW_CDEV_EVENT_RESPONSE:
Packit 713213
        if (!u.response.r.closure) {
Packit 713213
            dc1394_log_warning ("juju: Unsolicited response, rcode %x len %d",
Packit 713213
                    u.response.r.rcode, u.response.r.length);
Packit 713213
            break;
Packit 713213
        }
Packit 713213
        resp_info = u64_to_ptr(u.response.r.closure);
Packit 713213
        resp_info->rcode = u.response.r.rcode;
Packit 713213
        resp_info->actual_num_quads = u.response.r.length/4;
Packit 713213
        resp_info->got_response = 1;
Packit 713213
        if (resp_info->rcode || !resp_info->data)
Packit 713213
            break;
Packit 713213
        if (cam->max_response_quads < resp_info->actual_num_quads) {
Packit 713213
            dc1394_log_error ("juju: read buffer too small, have %d needed %d",
Packit 713213
                    cam->max_response_quads, resp_info->actual_num_quads);
Packit 713213
            break;
Packit 713213
        }
Packit 713213
Packit 713213
        len = MIN(resp_info->actual_num_quads, resp_info->num_quads);
Packit 713213
        for (i = 0; i < len; i++)
Packit 713213
            resp_info->data[i] = ntohl (u.response.r.data[i]);
Packit 713213
        break;
Packit 713213
Packit 713213
    case FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED:
Packit 713213
        if (!u.resource.closure) {
Packit 713213
            dc1394_log_warning ("juju: Spurious ISO allocation event: "
Packit 713213
                    "handle %d, chan %d, bw %d", u.resource.handle,
Packit 713213
                    u.resource.channel, u.resource.bandwidth);
Packit 713213
            break;
Packit 713213
        }
Packit 713213
        iso_info = u64_to_ptr(u.resource.closure);
Packit 713213
        if (iso_info->handle != u.resource.handle)
Packit 713213
            dc1394_log_warning ("juju: ISO alloc handle was %d, expected %d",
Packit 713213
                    u.resource.handle, iso_info->handle);
Packit 713213
        dc1394_log_debug ("juju: Allocated handle %d: chan %d bw %d",
Packit 713213
                u.resource.handle, u.resource.channel, u.resource.bandwidth);
Packit 713213
        iso_info->got_alloc = 1;
Packit 713213
        iso_info->channel = u.resource.channel;
Packit 713213
        iso_info->bandwidth = u.resource.bandwidth;
Packit 713213
        break;
Packit 713213
Packit 713213
    case FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED:
Packit 713213
        if (!u.resource.closure) {
Packit 713213
            dc1394_log_warning ("juju: Spurious ISO deallocation event: "
Packit 713213
                    "handle %d, chan %d, bw %d", u.resource.handle,
Packit 713213
                    u.resource.channel, u.resource.bandwidth);
Packit 713213
            break;
Packit 713213
        }
Packit 713213
        iso_info = u64_to_ptr(u.resource.closure);
Packit 713213
        if (iso_info->handle != u.resource.handle)
Packit 713213
            dc1394_log_warning ("juju: ISO dealloc handle was %d, expected %d",
Packit 713213
                    u.resource.handle, iso_info->handle);
Packit 713213
        dc1394_log_debug ("juju: Deallocated handle %d: chan %d bw %d",
Packit 713213
                u.resource.handle, u.resource.channel, u.resource.bandwidth);
Packit 713213
        iso_info->got_dealloc = 1;
Packit 713213
        iso_info->channel = u.resource.channel;
Packit 713213
        iso_info->bandwidth = u.resource.bandwidth;
Packit 713213
        break;
Packit 713213
Packit 713213
    default:
Packit 713213
        dc1394_log_warning ("juju: Unhandled event type %d",
Packit 713213
                u.reset.type);
Packit 713213
        break;
Packit 713213
    }
Packit 713213
Packit 713213
    return 0;
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
do_transaction(platform_camera_t * cam, int tcode, uint64_t offset,
Packit 713213
        const uint32_t * in, uint32_t * out, uint32_t num_quads)
Packit 713213
{
Packit 713213
    struct fw_cdev_send_request request;
Packit 713213
    juju_response_info resp;
Packit 713213
    int i, len;
Packit 713213
    uint32_t in_buffer[in ? num_quads : 0];
Packit 713213
    int retry = DC1394_MAX_RETRIES;
Packit 713213
Packit 713213
    for (i = 0; in && i < num_quads; i++)
Packit 713213
        in_buffer[i] = htonl (in[i]);
Packit 713213
Packit 713213
    resp.data = out;
Packit 713213
    resp.num_quads = out ? num_quads : 0;
Packit 713213
    cam->max_response_quads = resp.num_quads;
Packit 713213
Packit 713213
    request.closure = ptr_to_u64(&resp);
Packit 713213
    request.offset = CONFIG_ROM_BASE + offset;
Packit 713213
    request.data = ptr_to_u64(in_buffer);
Packit 713213
    request.length = num_quads * 4;
Packit 713213
    request.tcode = tcode;
Packit 713213
Packit 713213
    while (retry > 0) {
Packit 713213
        int retval;
Packit 713213
Packit 713213
        request.generation = cam->generation;
Packit 713213
Packit 713213
        int iotype = FW_CDEV_IOC_SEND_REQUEST;
Packit 713213
        if (cam->broadcast_enabled && (tcode == TCODE_WRITE_BLOCK_REQUEST ||
Packit 713213
                    tcode == TCODE_WRITE_QUADLET_REQUEST))
Packit 713213
            iotype = FW_CDEV_IOC_SEND_BROADCAST_REQUEST;
Packit 713213
Packit 713213
        len = ioctl (cam->fd, iotype, &request);
Packit 713213
        if (len < 0) {
Packit 713213
            dc1394_log_error("juju: Send request failed: %m");
Packit 713213
            return DC1394_FAILURE;
Packit 713213
        }
Packit 713213
Packit 713213
        resp.got_response = 0;
Packit 713213
        while (!resp.got_response)
Packit 713213
            if ((retval = juju_handle_event (cam)) < 0)
Packit 713213
                return retval;
Packit 713213
Packit 713213
        if (resp.rcode == 0) {
Packit 713213
            if (resp.num_quads != resp.actual_num_quads)
Packit 713213
                dc1394_log_warning("juju: Expected response len %d, got %d",
Packit 713213
                        resp.num_quads, resp.actual_num_quads);
Packit 713213
            return DC1394_SUCCESS;
Packit 713213
        }
Packit 713213
Packit 713213
        if (resp.rcode != RCODE_BUSY
Packit 713213
                && resp.rcode != RCODE_CONFLICT_ERROR
Packit 713213
                && resp.rcode != RCODE_GENERATION) {
Packit 713213
            dc1394_log_debug ("juju: Response error, rcode 0x%x",
Packit 713213
                    resp.rcode);
Packit 713213
            return DC1394_FAILURE;
Packit 713213
        }
Packit 713213
Packit 713213
        /* retry if we get any of the rcodes listed above */
Packit 713213
        dc1394_log_debug("juju: retry rcode 0x%x tcode 0x%x offset %"PRIx64,
Packit 713213
                resp.rcode, tcode, offset);
Packit 713213
        usleep (DC1394_SLOW_DOWN);
Packit 713213
        retry--;
Packit 713213
    }
Packit 713213
Packit 713213
    dc1394_log_error("juju: Max retries for tcode 0x%x, offset %"PRIx64,
Packit 713213
            tcode, offset);
Packit 713213
    return DC1394_FAILURE;
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_camera_read (platform_camera_t * cam, uint64_t offset, uint32_t * quads, int num_quads)
Packit 713213
{
Packit 713213
    int tcode;
Packit 713213
Packit 713213
    if (num_quads > 1)
Packit 713213
        tcode = TCODE_READ_BLOCK_REQUEST;
Packit 713213
    else
Packit 713213
        tcode = TCODE_READ_QUADLET_REQUEST;
Packit 713213
Packit 713213
    dc1394error_t err = do_transaction(cam, tcode, offset, NULL, quads, num_quads);
Packit 713213
    return err;
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_camera_write (platform_camera_t * cam, uint64_t offset, const uint32_t * quads, int num_quads)
Packit 713213
{
Packit 713213
    int tcode;
Packit 713213
Packit 713213
    if (num_quads > 1)
Packit 713213
        tcode = TCODE_WRITE_BLOCK_REQUEST;
Packit 713213
    else
Packit 713213
        tcode = TCODE_WRITE_QUADLET_REQUEST;
Packit 713213
Packit 713213
    return do_transaction(cam, tcode, offset, quads, NULL, num_quads);
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_reset_bus (platform_camera_t * cam)
Packit 713213
{
Packit 713213
    struct fw_cdev_initiate_bus_reset initiate;
Packit 713213
Packit 713213
    initiate.type = FW_CDEV_SHORT_RESET;
Packit 713213
    if (ioctl (cam->fd, FW_CDEV_IOC_INITIATE_BUS_RESET, &initiate) == 0)
Packit 713213
        return DC1394_SUCCESS;
Packit 713213
    else
Packit 713213
        return DC1394_FAILURE;
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_camera_get_node(platform_camera_t *cam, uint32_t *node,
Packit 713213
        uint32_t * generation)
Packit 713213
{
Packit 713213
    if (node)
Packit 713213
        *node = cam->node_id & 0x3f;  // mask out the bus ID
Packit 713213
    if (generation)
Packit 713213
        *generation = cam->generation;
Packit 713213
    return DC1394_SUCCESS;
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_read_cycle_timer (platform_camera_t * cam,
Packit 713213
        uint32_t * cycle_timer, uint64_t * local_time)
Packit 713213
{
Packit 713213
    struct fw_cdev_get_cycle_timer tm;
Packit 713213
Packit 713213
    if (ioctl(cam->fd, FW_CDEV_IOC_GET_CYCLE_TIMER, &tm) < 0) {
Packit 713213
        if (errno == EINVAL)
Packit 713213
            return DC1394_FUNCTION_NOT_SUPPORTED;
Packit 713213
        dc1394_log_error("Juju: get_cycle_timer ioctl failed: %m");
Packit 713213
        return DC1394_FAILURE;
Packit 713213
    }
Packit 713213
Packit 713213
    if (cycle_timer)
Packit 713213
        *cycle_timer = tm.cycle_timer;
Packit 713213
    if (local_time)
Packit 713213
        *local_time = tm.local_time;
Packit 713213
    return DC1394_SUCCESS;
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_set_broadcast(platform_camera_t * craw, dc1394bool_t pwr)
Packit 713213
{
Packit 713213
    if (pwr == DC1394_FALSE) {
Packit 713213
        craw->broadcast_enabled = 0;
Packit 713213
        return DC1394_SUCCESS;
Packit 713213
    }
Packit 713213
Packit 713213
    if (craw->broadcast_enabled)
Packit 713213
        return DC1394_SUCCESS;
Packit 713213
Packit 713213
    /* Test if the ioctl is available by sending a broadcast write to
Packit 713213
     * offset 0 that the kernel will always reject with EACCES if it is. */
Packit 713213
    struct fw_cdev_send_request request;
Packit 713213
    memset(&request, 0, sizeof(struct fw_cdev_send_request));
Packit 713213
    request.tcode = TCODE_WRITE_BLOCK_REQUEST;
Packit 713213
Packit 713213
    if (ioctl(craw->fd, FW_CDEV_IOC_SEND_BROADCAST_REQUEST, &request) != -1) {
Packit 713213
        dc1394_log_error("Juju: broadcast test succeeded unexpectedly\n");
Packit 713213
        return DC1394_FUNCTION_NOT_SUPPORTED;
Packit 713213
    }
Packit 713213
    if (errno == EINVAL)
Packit 713213
        return DC1394_FUNCTION_NOT_SUPPORTED;
Packit 713213
Packit 713213
    craw->broadcast_enabled = 1;
Packit 713213
    return DC1394_SUCCESS;
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_get_broadcast(platform_camera_t * craw, dc1394bool_t *pwr)
Packit 713213
{
Packit 713213
    if (craw->broadcast_enabled)
Packit 713213
        *pwr = DC1394_TRUE;
Packit 713213
    else
Packit 713213
        *pwr = DC1394_FALSE;
Packit 713213
Packit 713213
    return DC1394_SUCCESS;
Packit 713213
}
Packit 713213
Packit 713213
dc1394error_t
Packit 713213
juju_iso_allocate (platform_camera_t *cam, uint64_t allowed_channels,
Packit 713213
        int bandwidth_units, juju_iso_info **out)
Packit 713213
{
Packit 713213
    // Check kernel ABI version for ISO allocation support 
Packit 713213
    if (cam->kernel_abi_version < 2)
Packit 713213
        return DC1394_FUNCTION_NOT_SUPPORTED;
Packit 713213
Packit 713213
    juju_iso_info *res = add_iso_resource (cam);
Packit 713213
    if (!res)
Packit 713213
        return DC1394_MEMORY_ALLOCATION_FAILURE;
Packit 713213
Packit 713213
    struct fw_cdev_allocate_iso_resource request = {
Packit 713213
        .closure = ptr_to_u64(res),
Packit 713213
        .channels = allowed_channels,
Packit 713213
        .bandwidth = bandwidth_units,
Packit 713213
    };
Packit 713213
    if (ioctl (cam->fd, FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE, &request) < 0) {
Packit 713213
        remove_iso_resource (cam, res);
Packit 713213
        if (errno == EINVAL)
Packit 713213
            return DC1394_INVALID_ARGUMENT_VALUE;
Packit 713213
        return DC1394_FAILURE;
Packit 713213
    }
Packit 713213
    res->handle = request.handle;
Packit 713213
    dc1394_log_debug ("juju: Attempting iso allocation: "
Packit 713213
            "handle %d, chan 0x%"PRIx64", bw %d", request.handle,
Packit 713213
            request.channels, request.bandwidth);
Packit 713213
Packit 713213
    int ret;
Packit 713213
    while (!res->got_alloc)
Packit 713213
        if ((ret = juju_handle_event (cam)) < 0)
Packit 713213
            return ret;
Packit 713213
Packit 713213
    if (allowed_channels && res->channel < 0) {
Packit 713213
        remove_iso_resource (cam, res);
Packit 713213
        return DC1394_NO_ISO_CHANNEL;
Packit 713213
    }
Packit 713213
    if (bandwidth_units && !res->bandwidth) {
Packit 713213
        remove_iso_resource (cam, res);
Packit 713213
        return DC1394_NO_BANDWIDTH;
Packit 713213
    }
Packit 713213
Packit 713213
    if (out)
Packit 713213
        *out = res;
Packit 713213
    return DC1394_SUCCESS;
Packit 713213
}
Packit 713213
Packit 713213
dc1394error_t
Packit 713213
juju_iso_deallocate (platform_camera_t *cam, juju_iso_info * res)
Packit 713213
{
Packit 713213
    // Check kernel ABI version for ISO allocation support 
Packit 713213
    if (cam->kernel_abi_version < 2)
Packit 713213
        return DC1394_FUNCTION_NOT_SUPPORTED;
Packit 713213
Packit 713213
    if (res->got_dealloc) {
Packit 713213
        dc1394_log_warning ("juju: ISO resource was already released");
Packit 713213
        remove_iso_resource (cam, res);
Packit 713213
        return DC1394_SUCCESS;
Packit 713213
    }
Packit 713213
Packit 713213
    struct fw_cdev_allocate_iso_resource request = {
Packit 713213
        .handle = res->handle,
Packit 713213
    };
Packit 713213
    if (ioctl (cam->fd, FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE, &request) < 0) {
Packit 713213
        if (errno == EINVAL)
Packit 713213
            return DC1394_INVALID_ARGUMENT_VALUE;
Packit 713213
        return DC1394_FAILURE;
Packit 713213
    }
Packit 713213
Packit 713213
    int ret;
Packit 713213
    while (!res->got_dealloc)
Packit 713213
        if ((ret = juju_handle_event (cam)) < 0)
Packit 713213
            return ret;
Packit 713213
Packit 713213
    remove_iso_resource (cam, res);
Packit 713213
    return DC1394_SUCCESS;
Packit 713213
}
Packit 713213
Packit 713213
#if 0
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_iso_allocate_channel(platform_camera_t *cam, uint64_t allowed,
Packit 713213
            int *out_channel)
Packit 713213
{
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_iso_release_channel(platform_camera_t *cam, int channel)
Packit 713213
{
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_iso_allocate_bandwidth(platform_camera_t *cam, int units)
Packit 713213
{
Packit 713213
}
Packit 713213
Packit 713213
static dc1394error_t
Packit 713213
dc1394_juju_iso_release_bandwidth(platform_camera_t *cam, int units)
Packit 713213
{
Packit 713213
}
Packit 713213
#endif
Packit 713213
Packit 713213
static platform_dispatch_t
Packit 713213
juju_dispatch = {
Packit 713213
    .platform_new = dc1394_juju_new,
Packit 713213
    .platform_free = dc1394_juju_free,
Packit 713213
Packit 713213
    .get_device_list = dc1394_juju_get_device_list,
Packit 713213
    .free_device_list = dc1394_juju_free_device_list,
Packit 713213
    .device_get_config_rom = dc1394_juju_device_get_config_rom,
Packit 713213
Packit 713213
    .camera_new = dc1394_juju_camera_new,
Packit 713213
    .camera_free = dc1394_juju_camera_free,
Packit 713213
    .camera_set_parent = dc1394_juju_camera_set_parent,
Packit 713213
Packit 713213
    .camera_read = dc1394_juju_camera_read,
Packit 713213
    .camera_write = dc1394_juju_camera_write,
Packit 713213
Packit 713213
    .reset_bus = dc1394_juju_reset_bus,
Packit 713213
    .camera_print_info = dc1394_juju_camera_print_info,
Packit 713213
    .camera_get_node = dc1394_juju_camera_get_node,
Packit 713213
    .read_cycle_timer = dc1394_juju_read_cycle_timer,
Packit 713213
    .set_broadcast = dc1394_juju_set_broadcast,
Packit 713213
    .get_broadcast = dc1394_juju_get_broadcast,
Packit 713213
Packit 713213
    .capture_setup = dc1394_juju_capture_setup,
Packit 713213
    .capture_stop = dc1394_juju_capture_stop,
Packit 713213
    .capture_dequeue = dc1394_juju_capture_dequeue,
Packit 713213
    .capture_enqueue = dc1394_juju_capture_enqueue,
Packit 713213
    .capture_get_fileno = dc1394_juju_capture_get_fileno,
Packit 713213
    .capture_set_callback = NULL,
Packit 713213
    .capture_schedule_with_runloop = NULL,
Packit 713213
Packit 713213
    //.iso_allocate_channel = dc1394_juju_iso_allocate_channel,
Packit 713213
};
Packit 713213
Packit 713213
void
Packit 713213
juju_init(dc1394_t * d)
Packit 713213
{
Packit 713213
    register_platform (d, &juju_dispatch, "juju");
Packit 713213
}