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