1 /*
2 * 1394-Based Digital Camera Control Library
3 *
4 * Juju backend for dc1394
5 *
6 * Written by Kristian Hoegsberg <krh@bitplanet.net>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <dirent.h>
29 #include <fcntl.h>
30 #include <sys/ioctl.h>
31 #include <inttypes.h>
32 #include <arpa/inet.h>
33
34 #include "config.h"
35 #include "platform.h"
36 #include "internal.h"
37 #include "juju.h"
38
39 #define ptr_to_u64(p) ((__u64)(unsigned long)(p))
40 #define u64_to_ptr(p) ((void *)(unsigned long)(p))
41
42
43 static platform_t *
dc1394_juju_new(void)44 dc1394_juju_new (void)
45 {
46 DIR * dir;
47 struct dirent * de;
48 int num_devices = 0;
49
50 dir = opendir("/dev");
51 if (!dir) {
52 dc1394_log_error("Failed to create juju: opendir: %m");
53 return NULL;
54 }
55 while ((de = readdir(dir))) {
56 if (strncmp(de->d_name, "fw", 2) != 0)
57 continue;
58 dc1394_log_debug("Juju: Found /dev/%s", de->d_name);
59 num_devices++;
60 }
61 closedir(dir);
62
63 if (num_devices == 0) {
64 dc1394_log_debug("Juju: Found no devices /dev/fw*");
65 return NULL;
66 }
67
68 platform_t * p = calloc (1, sizeof (platform_t));
69 return p;
70 }
71 static void
dc1394_juju_free(platform_t * p)72 dc1394_juju_free (platform_t * p)
73 {
74 free (p);
75 }
76
77 struct _platform_device_t {
78 uint32_t config_rom[256];
79 char filename[32];
80 };
81
82 static platform_device_list_t *
dc1394_juju_get_device_list(platform_t * p)83 dc1394_juju_get_device_list (platform_t * p)
84 {
85 DIR * dir;
86 struct dirent * de;
87 platform_device_list_t * list;
88 uint32_t allocated_size = 64;
89
90 list = calloc (1, sizeof (platform_device_list_t));
91 if (!list)
92 return NULL;
93 list->devices = malloc(allocated_size * sizeof(platform_device_t *));
94 if (!list->devices) {
95 free (list);
96 return NULL;
97 }
98
99 dir = opendir("/dev");
100 if (dir == NULL) {
101 dc1394_log_error("opendir: %m");
102 free (list->devices);
103 free (list);
104 return NULL;
105 }
106
107 while ((de = readdir(dir))) {
108 char filename[262];
109 int fd;
110 platform_device_t * device;
111 struct fw_cdev_get_info get_info;
112 struct fw_cdev_event_bus_reset reset;
113
114 if (strncmp(de->d_name, "fw", 2) != 0 ||
115 de->d_name[2] < '0' || de->d_name[2] > '9')
116 continue;
117
118 snprintf(filename, sizeof filename, "/dev/%s", de->d_name);
119 fd = open(filename, O_RDWR);
120 if (fd < 0) {
121 dc1394_log_debug("Juju: Failed to open %s: %s", filename,
122 strerror (errno));
123 continue;
124 }
125 dc1394_log_debug("Juju: Opened %s successfully", filename);
126
127 device = malloc (sizeof (platform_device_t));
128 if (!device) {
129 close (fd);
130 continue;
131 }
132
133 get_info.version = FW_CDEV_VERSION;
134 get_info.rom = ptr_to_u64(&device->config_rom);
135 get_info.rom_length = 1024;
136 get_info.bus_reset = ptr_to_u64(&reset);
137 if (ioctl(fd, FW_CDEV_IOC_GET_INFO, &get_info) < 0) {
138 dc1394_log_error("GET_CONFIG_ROM failed for %s: %m",filename);
139 free (device);
140 close(fd);
141 continue;
142 }
143 close (fd);
144
145 strcpy (device->filename, filename);
146 list->devices[list->num_devices] = device;
147 list->num_devices++;
148
149 if (list->num_devices >= allocated_size) {
150 allocated_size += 64;
151 list->devices = realloc (list->devices, allocated_size * sizeof (platform_device_t *));
152 if (!list->devices)
153 return NULL;
154 }
155 }
156 closedir(dir);
157
158 return list;
159 }
160
161 static void
dc1394_juju_free_device_list(platform_device_list_t * d)162 dc1394_juju_free_device_list (platform_device_list_t * d)
163 {
164 int i;
165 for (i = 0; i < d->num_devices; i++)
166 free (d->devices[i]);
167 free (d->devices);
168 free (d);
169 }
170
171 static int
dc1394_juju_device_get_config_rom(platform_device_t * device,uint32_t * quads,int * num_quads)172 dc1394_juju_device_get_config_rom (platform_device_t * device,
173 uint32_t * quads, int * num_quads)
174 {
175 if (*num_quads > 256)
176 *num_quads = 256;
177
178 memcpy (quads, device->config_rom, *num_quads * sizeof (uint32_t));
179 return 0;
180 }
181
182 static juju_iso_info *
add_iso_resource(platform_camera_t * cam)183 add_iso_resource (platform_camera_t *cam)
184 {
185 juju_iso_info *res = calloc (1, sizeof (juju_iso_info));
186 if (!res)
187 return NULL;
188 res->next = cam->iso_resources;
189 cam->iso_resources = res;
190 return res;
191 }
192
193 static void
remove_iso_resource(platform_camera_t * cam,juju_iso_info * res)194 remove_iso_resource (platform_camera_t *cam, juju_iso_info * res)
195 {
196 juju_iso_info **ptr = &cam->iso_resources;
197 while (*ptr) {
198 if (*ptr == res) {
199 *ptr = res->next;
200 free (res);
201 return;
202 }
203 ptr = &(*ptr)->next;
204 }
205 }
206
207 static platform_camera_t *
dc1394_juju_camera_new(platform_t * p,platform_device_t * device,uint32_t unit_directory_offset)208 dc1394_juju_camera_new (platform_t * p, platform_device_t * device, uint32_t unit_directory_offset)
209 {
210 int fd;
211 platform_camera_t * camera;
212 struct fw_cdev_get_info get_info;
213 struct fw_cdev_event_bus_reset reset;
214
215 fd = open(device->filename, O_RDWR);
216 if (fd < 0) {
217 dc1394_log_error("could not open device %s: %m", device->filename);
218 return NULL;
219 }
220
221 get_info.version = FW_CDEV_VERSION;
222 get_info.rom = 0;
223 get_info.rom_length = 0;
224 get_info.bus_reset = ptr_to_u64(&reset);
225 if (ioctl(fd, FW_CDEV_IOC_GET_INFO, &get_info) < 0) {
226 dc1394_log_error("IOC_GET_INFO failed for a device %s: %m",device->filename);
227 close(fd);
228 return NULL;
229 }
230
231 dc1394_log_debug("Juju: kernel API has version %d", get_info.version);
232
233 camera = calloc (1, sizeof (platform_camera_t));
234 camera->fd = fd;
235 camera->generation = reset.generation;
236 camera->node_id = reset.node_id;
237 strcpy (camera->filename, device->filename);
238
239 camera->header_size = 4;
240 if (get_info.version >= 2)
241 camera->header_size = 8;
242
243 camera->kernel_abi_version=get_info.version;
244
245 return camera;
246 }
247
dc1394_juju_camera_free(platform_camera_t * cam)248 static void dc1394_juju_camera_free (platform_camera_t * cam)
249 {
250 while (cam->iso_resources)
251 remove_iso_resource (cam, cam->iso_resources);
252 close (cam->fd);
253 free (cam);
254 }
255
256 static void
dc1394_juju_camera_set_parent(platform_camera_t * cam,dc1394camera_t * parent)257 dc1394_juju_camera_set_parent (platform_camera_t * cam, dc1394camera_t * parent)
258 {
259 cam->camera = parent;
260 }
261
262 static dc1394error_t
dc1394_juju_camera_print_info(platform_camera_t * camera,FILE * fd)263 dc1394_juju_camera_print_info (platform_camera_t * camera, FILE *fd)
264 {
265 fprintf(fd,"------ Camera platform-specific information ------\n");
266 fprintf(fd,"Device filename : %s\n", camera->filename);
267 return DC1394_SUCCESS;
268 }
269
270 #define MIN(a,b) ((a) < (b) ? (a) : (b))
271
272 typedef struct _juju_response_info {
273 int got_response;
274 uint32_t rcode;
275 uint32_t *data;
276 int num_quads;
277 int actual_num_quads;
278 } juju_response_info;
279
280 static int
juju_handle_event(platform_camera_t * cam)281 juju_handle_event (platform_camera_t * cam)
282 {
283 union {
284 struct {
285 struct fw_cdev_event_response r;
286 __u32 buffer[cam->max_response_quads];
287 } response;
288 struct fw_cdev_event_bus_reset reset;
289 struct fw_cdev_event_iso_resource resource;
290 } u;
291 int len, i;
292 juju_response_info *resp_info;
293 juju_iso_info *iso_info;
294
295 len = read (cam->fd, &u, sizeof u);
296 if (len < 0) {
297 dc1394_log_error("juju: Read failed: %m");
298 return -1;
299 }
300
301 switch (u.reset.type) {
302 case FW_CDEV_EVENT_BUS_RESET:
303 cam->generation = u.reset.generation;
304 cam->node_id = u.reset.node_id;
305 dc1394_log_debug ("juju: Bus reset, gen %d, node 0x%x",
306 cam->generation, cam->node_id);
307 break;
308
309 case FW_CDEV_EVENT_RESPONSE:
310 if (!u.response.r.closure) {
311 dc1394_log_warning ("juju: Unsolicited response, rcode %x len %d",
312 u.response.r.rcode, u.response.r.length);
313 break;
314 }
315 resp_info = u64_to_ptr(u.response.r.closure);
316 resp_info->rcode = u.response.r.rcode;
317 resp_info->actual_num_quads = u.response.r.length/4;
318 resp_info->got_response = 1;
319 if (resp_info->rcode || !resp_info->data)
320 break;
321 if (cam->max_response_quads < resp_info->actual_num_quads) {
322 dc1394_log_error ("juju: read buffer too small, have %d needed %d",
323 cam->max_response_quads, resp_info->actual_num_quads);
324 break;
325 }
326
327 len = MIN(resp_info->actual_num_quads, resp_info->num_quads);
328 for (i = 0; i < len; i++)
329 resp_info->data[i] = ntohl (u.response.r.data[i]);
330 break;
331
332 case FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED:
333 if (!u.resource.closure) {
334 dc1394_log_warning ("juju: Spurious ISO allocation event: "
335 "handle %d, chan %d, bw %d", u.resource.handle,
336 u.resource.channel, u.resource.bandwidth);
337 break;
338 }
339 iso_info = u64_to_ptr(u.resource.closure);
340 if (iso_info->handle != u.resource.handle)
341 dc1394_log_warning ("juju: ISO alloc handle was %d, expected %d",
342 u.resource.handle, iso_info->handle);
343 dc1394_log_debug ("juju: Allocated handle %d: chan %d bw %d",
344 u.resource.handle, u.resource.channel, u.resource.bandwidth);
345 iso_info->got_alloc = 1;
346 iso_info->channel = u.resource.channel;
347 iso_info->bandwidth = u.resource.bandwidth;
348 break;
349
350 case FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED:
351 if (!u.resource.closure) {
352 dc1394_log_warning ("juju: Spurious ISO deallocation event: "
353 "handle %d, chan %d, bw %d", u.resource.handle,
354 u.resource.channel, u.resource.bandwidth);
355 break;
356 }
357 iso_info = u64_to_ptr(u.resource.closure);
358 if (iso_info->handle != u.resource.handle)
359 dc1394_log_warning ("juju: ISO dealloc handle was %d, expected %d",
360 u.resource.handle, iso_info->handle);
361 dc1394_log_debug ("juju: Deallocated handle %d: chan %d bw %d",
362 u.resource.handle, u.resource.channel, u.resource.bandwidth);
363 iso_info->got_dealloc = 1;
364 iso_info->channel = u.resource.channel;
365 iso_info->bandwidth = u.resource.bandwidth;
366 break;
367
368 default:
369 dc1394_log_warning ("juju: Unhandled event type %d",
370 u.reset.type);
371 break;
372 }
373
374 return 0;
375 }
376
377 static dc1394error_t
do_transaction(platform_camera_t * cam,int tcode,uint64_t offset,const uint32_t * in,uint32_t * out,uint32_t num_quads)378 do_transaction(platform_camera_t * cam, int tcode, uint64_t offset,
379 const uint32_t * in, uint32_t * out, uint32_t num_quads)
380 {
381 struct fw_cdev_send_request request;
382 juju_response_info resp;
383 int i, len;
384 uint32_t in_buffer[in ? num_quads : 0];
385 int retry = DC1394_MAX_RETRIES;
386
387 for (i = 0; in && i < num_quads; i++)
388 in_buffer[i] = htonl (in[i]);
389
390 resp.data = out;
391 resp.num_quads = out ? num_quads : 0;
392 cam->max_response_quads = resp.num_quads;
393
394 request.closure = ptr_to_u64(&resp);
395 request.offset = CONFIG_ROM_BASE + offset;
396 request.data = ptr_to_u64(in_buffer);
397 request.length = num_quads * 4;
398 request.tcode = tcode;
399
400 while (retry > 0) {
401 int retval;
402
403 request.generation = cam->generation;
404
405 int iotype = FW_CDEV_IOC_SEND_REQUEST;
406 if (cam->broadcast_enabled && (tcode == TCODE_WRITE_BLOCK_REQUEST ||
407 tcode == TCODE_WRITE_QUADLET_REQUEST))
408 iotype = FW_CDEV_IOC_SEND_BROADCAST_REQUEST;
409
410 len = ioctl (cam->fd, iotype, &request);
411 if (len < 0) {
412 dc1394_log_error("juju: Send request failed: %m");
413 return DC1394_FAILURE;
414 }
415
416 resp.got_response = 0;
417 while (!resp.got_response)
418 if ((retval = juju_handle_event (cam)) < 0)
419 return retval;
420
421 if (resp.rcode == 0) {
422 if (resp.num_quads != resp.actual_num_quads)
423 dc1394_log_warning("juju: Expected response len %d, got %d",
424 resp.num_quads, resp.actual_num_quads);
425 return DC1394_SUCCESS;
426 }
427
428 if (resp.rcode != RCODE_BUSY
429 && resp.rcode != RCODE_CONFLICT_ERROR
430 && resp.rcode != RCODE_GENERATION) {
431 dc1394_log_debug ("juju: Response error, rcode 0x%x",
432 resp.rcode);
433 return DC1394_FAILURE;
434 }
435
436 /* retry if we get any of the rcodes listed above */
437 dc1394_log_debug("juju: retry rcode 0x%x tcode 0x%x offset %"PRIx64,
438 resp.rcode, tcode, offset);
439 usleep (DC1394_SLOW_DOWN);
440 retry--;
441 }
442
443 dc1394_log_error("juju: Max retries for tcode 0x%x, offset %"PRIx64,
444 tcode, offset);
445 return DC1394_FAILURE;
446 }
447
448 static dc1394error_t
dc1394_juju_camera_read(platform_camera_t * cam,uint64_t offset,uint32_t * quads,int num_quads)449 dc1394_juju_camera_read (platform_camera_t * cam, uint64_t offset, uint32_t * quads, int num_quads)
450 {
451 int tcode;
452
453 if (num_quads > 1)
454 tcode = TCODE_READ_BLOCK_REQUEST;
455 else
456 tcode = TCODE_READ_QUADLET_REQUEST;
457
458 dc1394error_t err = do_transaction(cam, tcode, offset, NULL, quads, num_quads);
459 return err;
460 }
461
462 static dc1394error_t
dc1394_juju_camera_write(platform_camera_t * cam,uint64_t offset,const uint32_t * quads,int num_quads)463 dc1394_juju_camera_write (platform_camera_t * cam, uint64_t offset, const uint32_t * quads, int num_quads)
464 {
465 int tcode;
466
467 if (num_quads > 1)
468 tcode = TCODE_WRITE_BLOCK_REQUEST;
469 else
470 tcode = TCODE_WRITE_QUADLET_REQUEST;
471
472 return do_transaction(cam, tcode, offset, quads, NULL, num_quads);
473 }
474
475 static dc1394error_t
dc1394_juju_reset_bus(platform_camera_t * cam)476 dc1394_juju_reset_bus (platform_camera_t * cam)
477 {
478 struct fw_cdev_initiate_bus_reset initiate;
479
480 initiate.type = FW_CDEV_SHORT_RESET;
481 if (ioctl (cam->fd, FW_CDEV_IOC_INITIATE_BUS_RESET, &initiate) == 0)
482 return DC1394_SUCCESS;
483 else
484 return DC1394_FAILURE;
485 }
486
487 static dc1394error_t
dc1394_juju_camera_get_node(platform_camera_t * cam,uint32_t * node,uint32_t * generation)488 dc1394_juju_camera_get_node(platform_camera_t *cam, uint32_t *node,
489 uint32_t * generation)
490 {
491 if (node)
492 *node = cam->node_id & 0x3f; // mask out the bus ID
493 if (generation)
494 *generation = cam->generation;
495 return DC1394_SUCCESS;
496 }
497
498 static dc1394error_t
dc1394_juju_read_cycle_timer(platform_camera_t * cam,uint32_t * cycle_timer,uint64_t * local_time)499 dc1394_juju_read_cycle_timer (platform_camera_t * cam,
500 uint32_t * cycle_timer, uint64_t * local_time)
501 {
502 struct fw_cdev_get_cycle_timer tm;
503
504 if (ioctl(cam->fd, FW_CDEV_IOC_GET_CYCLE_TIMER, &tm) < 0) {
505 if (errno == EINVAL)
506 return DC1394_FUNCTION_NOT_SUPPORTED;
507 dc1394_log_error("Juju: get_cycle_timer ioctl failed: %m");
508 return DC1394_FAILURE;
509 }
510
511 if (cycle_timer)
512 *cycle_timer = tm.cycle_timer;
513 if (local_time)
514 *local_time = tm.local_time;
515 return DC1394_SUCCESS;
516 }
517
518 static dc1394error_t
dc1394_juju_set_broadcast(platform_camera_t * craw,dc1394bool_t pwr)519 dc1394_juju_set_broadcast(platform_camera_t * craw, dc1394bool_t pwr)
520 {
521 if (pwr == DC1394_FALSE) {
522 craw->broadcast_enabled = 0;
523 return DC1394_SUCCESS;
524 }
525
526 if (craw->broadcast_enabled)
527 return DC1394_SUCCESS;
528
529 /* Test if the ioctl is available by sending a broadcast write to
530 * offset 0 that the kernel will always reject with EACCES if it is. */
531 struct fw_cdev_send_request request;
532 memset(&request, 0, sizeof(struct fw_cdev_send_request));
533 request.tcode = TCODE_WRITE_BLOCK_REQUEST;
534
535 if (ioctl(craw->fd, FW_CDEV_IOC_SEND_BROADCAST_REQUEST, &request) != -1) {
536 dc1394_log_error("Juju: broadcast test succeeded unexpectedly\n");
537 return DC1394_FUNCTION_NOT_SUPPORTED;
538 }
539 if (errno == EINVAL)
540 return DC1394_FUNCTION_NOT_SUPPORTED;
541
542 craw->broadcast_enabled = 1;
543 return DC1394_SUCCESS;
544 }
545
546 static dc1394error_t
dc1394_juju_get_broadcast(platform_camera_t * craw,dc1394bool_t * pwr)547 dc1394_juju_get_broadcast(platform_camera_t * craw, dc1394bool_t *pwr)
548 {
549 if (craw->broadcast_enabled)
550 *pwr = DC1394_TRUE;
551 else
552 *pwr = DC1394_FALSE;
553
554 return DC1394_SUCCESS;
555 }
556
557 dc1394error_t
juju_iso_allocate(platform_camera_t * cam,uint64_t allowed_channels,int bandwidth_units,juju_iso_info ** out)558 juju_iso_allocate (platform_camera_t *cam, uint64_t allowed_channels,
559 int bandwidth_units, juju_iso_info **out)
560 {
561 // Check kernel ABI version for ISO allocation support
562 if (cam->kernel_abi_version < 2)
563 return DC1394_FUNCTION_NOT_SUPPORTED;
564
565 juju_iso_info *res = add_iso_resource (cam);
566 if (!res)
567 return DC1394_MEMORY_ALLOCATION_FAILURE;
568
569 struct fw_cdev_allocate_iso_resource request = {
570 .closure = ptr_to_u64(res),
571 .channels = allowed_channels,
572 .bandwidth = bandwidth_units,
573 };
574 if (ioctl (cam->fd, FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE, &request) < 0) {
575 remove_iso_resource (cam, res);
576 if (errno == EINVAL)
577 return DC1394_INVALID_ARGUMENT_VALUE;
578 return DC1394_FAILURE;
579 }
580 res->handle = request.handle;
581 dc1394_log_debug ("juju: Attempting iso allocation: "
582 "handle %d, chan 0x%"PRIx64", bw %d", request.handle,
583 request.channels, request.bandwidth);
584
585 int ret;
586 while (!res->got_alloc)
587 if ((ret = juju_handle_event (cam)) < 0)
588 return ret;
589
590 if (allowed_channels && res->channel < 0) {
591 remove_iso_resource (cam, res);
592 return DC1394_NO_ISO_CHANNEL;
593 }
594 if (bandwidth_units && !res->bandwidth) {
595 remove_iso_resource (cam, res);
596 return DC1394_NO_BANDWIDTH;
597 }
598
599 if (out)
600 *out = res;
601 return DC1394_SUCCESS;
602 }
603
604 dc1394error_t
juju_iso_deallocate(platform_camera_t * cam,juju_iso_info * res)605 juju_iso_deallocate (platform_camera_t *cam, juju_iso_info * res)
606 {
607 // Check kernel ABI version for ISO allocation support
608 if (cam->kernel_abi_version < 2)
609 return DC1394_FUNCTION_NOT_SUPPORTED;
610
611 if (res->got_dealloc) {
612 dc1394_log_warning ("juju: ISO resource was already released");
613 remove_iso_resource (cam, res);
614 return DC1394_SUCCESS;
615 }
616
617 struct fw_cdev_allocate_iso_resource request = {
618 .handle = res->handle,
619 };
620 if (ioctl (cam->fd, FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE, &request) < 0) {
621 if (errno == EINVAL)
622 return DC1394_INVALID_ARGUMENT_VALUE;
623 return DC1394_FAILURE;
624 }
625
626 int ret;
627 while (!res->got_dealloc)
628 if ((ret = juju_handle_event (cam)) < 0)
629 return ret;
630
631 remove_iso_resource (cam, res);
632 return DC1394_SUCCESS;
633 }
634
635 #if 0
636 static dc1394error_t
637 dc1394_juju_iso_allocate_channel(platform_camera_t *cam, uint64_t allowed,
638 int *out_channel)
639 {
640 }
641
642 static dc1394error_t
643 dc1394_juju_iso_release_channel(platform_camera_t *cam, int channel)
644 {
645 }
646
647 static dc1394error_t
648 dc1394_juju_iso_allocate_bandwidth(platform_camera_t *cam, int units)
649 {
650 }
651
652 static dc1394error_t
653 dc1394_juju_iso_release_bandwidth(platform_camera_t *cam, int units)
654 {
655 }
656 #endif
657
658 static platform_dispatch_t
659 juju_dispatch = {
660 .platform_new = dc1394_juju_new,
661 .platform_free = dc1394_juju_free,
662
663 .get_device_list = dc1394_juju_get_device_list,
664 .free_device_list = dc1394_juju_free_device_list,
665 .device_get_config_rom = dc1394_juju_device_get_config_rom,
666
667 .camera_new = dc1394_juju_camera_new,
668 .camera_free = dc1394_juju_camera_free,
669 .camera_set_parent = dc1394_juju_camera_set_parent,
670
671 .camera_read = dc1394_juju_camera_read,
672 .camera_write = dc1394_juju_camera_write,
673
674 .reset_bus = dc1394_juju_reset_bus,
675 .camera_print_info = dc1394_juju_camera_print_info,
676 .camera_get_node = dc1394_juju_camera_get_node,
677 .read_cycle_timer = dc1394_juju_read_cycle_timer,
678 .set_broadcast = dc1394_juju_set_broadcast,
679 .get_broadcast = dc1394_juju_get_broadcast,
680
681 .capture_setup = dc1394_juju_capture_setup,
682 .capture_stop = dc1394_juju_capture_stop,
683 .capture_dequeue = dc1394_juju_capture_dequeue,
684 .capture_enqueue = dc1394_juju_capture_enqueue,
685 .capture_get_fileno = dc1394_juju_capture_get_fileno,
686 .capture_set_callback = NULL,
687 .capture_schedule_with_runloop = NULL,
688
689 //.iso_allocate_channel = dc1394_juju_iso_allocate_channel,
690 };
691
692 void
juju_init(dc1394_t * d)693 juju_init(dc1394_t * d)
694 {
695 register_platform (d, &juju_dispatch, "juju");
696 }
697