diff --git a/NEWS b/NEWS index e69de29..6072e74 100644 --- a/NEWS +++ b/NEWS @@ -0,0 +1,10 @@ + +Version 0.4: + +- isochronous receive support + +Version 0.3: + +- first release of new libraw1394 for new raw1394 driver +- supports 1394 async reads/writes +- maintainer: Andreas Bombe diff --git a/configure.in b/configure.in index 1179638..39802f8 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ # process this file with autoconf to get a configure script AC_INIT(Makefile.am) -AM_INIT_AUTOMAKE(libraw1394, 0.3) +AM_INIT_AUTOMAKE(libraw1394, 0.4) AC_PROG_CC AM_PROG_LIBTOOL diff --git a/src/Makefile.am b/src/Makefile.am index 4905126..ab32929 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,12 +3,13 @@ lib_LTLIBRARIES = libraw1394.la -libraw1394_la_LDFLAGS = -version-info 0:0:0 +libraw1394_la_LDFLAGS = -version-info 1:0:1 libraw1394_la_SOURCES = \ main.c \ eventloop.c \ readwrite.c \ + iso.c \ kernel-raw1394.h \ raw1394_private.h diff --git a/src/iso.c b/src/iso.c new file mode 100644 index 0000000..21abeae --- /dev/null +++ b/src/iso.c @@ -0,0 +1,64 @@ + +#include +#include + +#include "raw1394.h" +#include "kernel-raw1394.h" +#include "raw1394_private.h" + + +static int do_iso_listen(struct raw1394_handle *handle, int channel) +{ + struct sync_cb_data sd = { 0, 0 }; + struct raw1394_reqhandle rh = { (req_callback_t)_raw1394_sync_cb, &sd }; + int err; + struct raw1394_request *req = &handle->req; + + CLEAR_REQ(req); + req->type = RAW1394_REQ_ISO_LISTEN; + req->generation = handle->generation; + req->misc = channel; + req->tag = (unsigned long)&rh; + req->recvb = handle->buffer; + req->length = HBUF_SIZE; + + err = write(handle->fd, req, sizeof(*req)); + while (!sd.done) { + if (err < 0) return err; + err = raw1394_loop_iterate(handle); + } + + switch (sd.errcode) { + case RAW1394_ERROR_ALREADY: + errno = EALREADY; + return -1; + + case RAW1394_ERROR_INVALID_ARG: + errno = EINVAL; + return -1; + + default: + errno = 0; + return sd.errcode; + } +} + +int raw1394_start_iso_rcv(struct raw1394_handle *handle, unsigned int channel) +{ + if (channel > 63) { + errno = EINVAL; + return -1; + } + + return do_iso_listen(handle, channel); +} + +int raw1394_stop_iso_rcv(struct raw1394_handle *handle, unsigned int channel) +{ + if (channel > 63) { + errno = EINVAL; + return -1; + } + + return do_iso_listen(handle, ~channel); +} diff --git a/src/kernel-raw1394.h b/src/kernel-raw1394.h index fe8ea72..b1b0e4b 100644 --- a/src/kernel-raw1394.h +++ b/src/kernel-raw1394.h @@ -65,6 +65,11 @@ struct raw1394_khost_list { #ifdef __KERNEL__ +struct iso_block_store { + atomic_t refcount; + quadlet_t data[0]; +}; + struct file_info { struct list_head list; @@ -79,6 +84,8 @@ struct file_info { wait_queue_head_t poll_wait_complete; u64 listen_channels; + quadlet_t *iso_buffer; + size_t iso_buffer_length; }; struct pending_request { @@ -86,6 +93,7 @@ struct pending_request { struct file_info *file_info; struct hpsb_packet *packet; struct tq_struct tq; + struct iso_block_store *ibs; quadlet_t *data; int free_data; struct raw1394_request req; diff --git a/src/main.c b/src/main.c index 7cc8fe1..d268f0b 100644 --- a/src/main.c +++ b/src/main.c @@ -33,6 +33,16 @@ static int iso_handler_default(struct raw1394_handle *handle, int channel, return 0; } +int _raw1394_sync_cb(struct raw1394_handle *unused, struct sync_cb_data *data, + int error) +{ + data->errcode = error; + data->done = 1; + return 0; +} + + + static unsigned int init_rawdevice(struct raw1394_handle *h) { diff --git a/src/raw1394.h b/src/raw1394.h index d1fe443..849369e 100644 --- a/src/raw1394.h +++ b/src/raw1394.h @@ -64,6 +64,10 @@ int raw1394_set_port(raw1394handle_t handle, int port); * registering functions. This function will return -1 for an error or the * return value of the handler which got executed. Default handlers always * return zero. + * + * Note that some other library functions may call this function multiple times + * to wait for their completion, some handler return values may get lost if you + * use these. */ int raw1394_loop_iterate(raw1394handle_t handle); @@ -88,8 +92,6 @@ tag_handler_t raw1394_set_tag_handler(raw1394handle_t handle, * Set the handler that will be called when an iso packet arrives (data points * to the iso packet header). The default action is to do nothing. Returns old * handler. - * - * Iso receive is not implemented yet. */ typedef int (*iso_handler_t)(raw1394handle_t, int channel, size_t length, quadlet_t *data); @@ -112,23 +114,27 @@ struct raw1394_reqhandle { * Passes custom tag. Use pointer to raw1394_reqhandle if you use the standard * tag handler. */ -int raw1394_start_read(struct raw1394_handle *handle, nodeid_t node, - nodeaddr_t addr, size_t length, quadlet_t *buffer, - unsigned long tag); -int raw1394_start_write(struct raw1394_handle *handle, nodeid_t node, - nodeaddr_t addr, size_t length, quadlet_t *data, - unsigned long tag); +int raw1394_start_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, + size_t length, quadlet_t *buffer, unsigned long tag); +int raw1394_start_write(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, + size_t length, quadlet_t *data, unsigned long tag); /* * This does the complete transaction and will return when it's finished. It * will call raw1394_loop_iterate() as often as necessary, return values of * handlers called will be therefore lost. */ -int raw1394_read(struct raw1394_handle *handle, nodeid_t node, nodeaddr_t addr, +int raw1394_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, size_t length, quadlet_t *buffer); -int raw1394_write(struct raw1394_handle *handle, nodeid_t node, nodeaddr_t addr, +int raw1394_write(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, size_t length, quadlet_t *data); +/* + * Start and stop receiving a certain isochronous channel. You have to set an + * iso handler (see above). You can receive multiple channels simultaneously. + */ +int raw1394_start_iso_rcv(raw1394handle_t handle, unsigned int channel); +int raw1394_stop_iso_rcv(raw1394handle_t handle, unsigned int channel); #ifdef __cplusplus } diff --git a/src/raw1394_private.h b/src/raw1394_private.h index 06c2746..c570d4b 100644 --- a/src/raw1394_private.h +++ b/src/raw1394_private.h @@ -17,6 +17,13 @@ struct raw1394_handle { quadlet_t buffer[2048]; }; +struct sync_cb_data { + int done; + int errcode; +}; + +int _raw1394_sync_cb(struct raw1394_handle*, struct sync_cb_data*, int); + #define HBUF_SIZE 8192 #define CLEAR_REQ(reqp) memset((reqp), 0, sizeof(struct raw1394_request)) diff --git a/src/readwrite.c b/src/readwrite.c index 37e9f71..192b0a1 100644 --- a/src/readwrite.c +++ b/src/readwrite.c @@ -6,20 +6,6 @@ #include "raw1394_private.h" -struct sync_cb_data { - int done; - int errcode; -}; - -static int sync_cb(struct raw1394_handle *unused, - struct sync_cb_data *data, int error) -{ - data->errcode = error; - data->done = 1; - return 0; -} - - int raw1394_start_read(struct raw1394_handle *handle, nodeid_t node, nodeaddr_t addr, size_t length, quadlet_t *buffer, unsigned long tag) @@ -60,14 +46,17 @@ int raw1394_start_write(struct raw1394_handle *handle, nodeid_t node, -#define SYNCFUNC_VARS \ - struct sync_cb_data sd = { 0, 0 }; \ - struct raw1394_reqhandle rh = { (req_callback_t)sync_cb, &sd }; \ +#define SYNCFUNC_VARS \ + struct sync_cb_data sd = { 0, 0 }; \ + struct raw1394_reqhandle rh = { (req_callback_t)_raw1394_sync_cb, \ + &sd }; \ int err -#define SYNCFUNC_BODY \ - if (err < 0) return err; \ - while (!sd.done) raw1394_loop_iterate(handle); \ +#define SYNCFUNC_BODY \ + while (!sd.done) { \ + if (err < 0) return err; \ + err = raw1394_loop_iterate(handle); \ + } \ return sd.errcode int raw1394_read(struct raw1394_handle *handle, nodeid_t node, nodeaddr_t addr,