|
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 |
}
|