summaryrefslogtreecommitdiffstats
path: root/src/eventloop.c
blob: c360a639ab15c2aef64a9e44d56859a1ef61d5e9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/*
 * libraw1394 - library for raw access to the 1394 bus with the Linux subsystem.
 *
 * Copyright (C) 1999,2000,2001,2002 Andreas Bombe
 *                     2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
 *                     2002 Christian Toegel <christian.toegel@gmx.at>
 *
 * This library is licensed under the GNU Lesser General Public License (LGPL),
 * version 2.1 or later. See the file COPYING.LIB in the distribution for
 * details.
 *
 *
 * Contributions:
 *
 * Manfred Weihs <weihs@ict.tuwien.ac.at>
 *        address range mapping
 * Christian Toegel <christian.toegel@gmx.at>
 *        address range mapping
 */

#include <config.h>
#include <unistd.h>
#include <byteswap.h>

#include "raw1394.h"
#include "kernel-raw1394.h"
#include "raw1394_private.h"


/**
 * raw1394_loop_iterate - get and process one event message
 *
 * Get one new message through handle and process it with the registered message
 * handler.  This function will return %-1 for an error or the return value of
 * the handler which got executed.  The 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(struct raw1394_handle *handle)
{
        struct raw1394_request *req = &handle->req;
        int retval = 0, channel;

        if (read(handle->fd, req, sizeof(*req)) < 0) {
                return -1;
        }

        switch (req->type) {
        case RAW1394_REQ_BUS_RESET:
                if (handle->protocol_version == 3) {
                        handle->num_of_nodes = req->misc & 0xffff;
                        handle->local_id = req->misc >> 16;
                } else {
                        handle->num_of_nodes = req->misc & 0xff;
                        handle->irm_id = ((req->misc >> 8) & 0xff) | 0xffc0;
                        handle->local_id = req->misc >> 16;
                }

                if (handle->bus_reset_handler) {
                        retval = handle->bus_reset_handler(handle,
                                                           req->generation);
                }
                break;

        case RAW1394_REQ_ISO_RECEIVE:
                channel = (handle->buffer[0] >> 8) & 0x3f;
#ifndef WORDS_BIGENDIAN
                handle->buffer[0] = bswap_32(handle->buffer[0]);
#endif

                if (handle->iso_handler[channel]) {
                        retval = handle->iso_handler[channel](handle, channel,
                                                              req->length,
                                                              handle->buffer);
                }
                break;

        case RAW1394_REQ_FCP_REQUEST:
                if (handle->fcp_handler) {
                        retval = handle->fcp_handler(handle, req->misc & 0xffff,
                                                     req->misc >> 16,
                                                     req->length,
                                                     (char *)handle->buffer);
                }
                break;

        case RAW1394_REQ_ARM:
                if (handle->arm_tag_handler) {
                        retval = handle->arm_tag_handler(handle, req->tag,
                                 (req->misc & (0xFF)), 
                                 ((req->misc >> 16) & (0xFFFF)),
                                 int2ptr(req->recvb));
                } 
                break;
                
        case RAW1394_REQ_ECHO:
                retval=req->misc;
                break;

        case RAW1394_REQ_RAWISO_ACTIVITY:
                retval = _raw1394_iso_iterate(handle);
                break;
        
        default:
                if (handle->tag_handler) {
                        retval = handle->tag_handler(handle, req->tag,
                                                     req->error);
                }
                break;
        }

        return retval;
}


/**
 * raw1394_set_bus_reset_handler - set bus reset handler
 * @new_h: pointer to new handler
 *
 * Sets the handler to be called on every bus reset to @new_h and returns the
 * old handler. The default handler just calls raw1394_update_generation().
 **/
bus_reset_handler_t raw1394_set_bus_reset_handler(struct raw1394_handle *handle,
                                                  bus_reset_handler_t new)
{
        bus_reset_handler_t old;

        old = handle->bus_reset_handler;
        handle->bus_reset_handler = new;

        return old;
}

/**
 * raw1394_set_tag_handler - set request completion handler
 * @new_h: pointer to new handler
 *
 * Sets the handler to be called whenever a request completes to @new_h and
 * returns the old handler.  The default handler interprets the tag as a pointer
 * to a &struct raw1394_reqhandle and calls the callback in there.
 *
 * Care must be taken when replacing the tag handler and calling the synchronous
 * versions of the transaction functions (i.e. raw1394_read(), raw1394_write(),
 * raw1394_lock(), raw1394_iso_write()) since these do pass pointers to &struct
 * raw1394_reqhandle as the tag and expect the callback to be invoked.
 **/
tag_handler_t raw1394_set_tag_handler(struct raw1394_handle *handle, 
                                      tag_handler_t new)
{
        tag_handler_t old;

        old = handle->tag_handler;
        handle->tag_handler = new;

        return old;
}

arm_tag_handler_t raw1394_set_arm_tag_handler(struct raw1394_handle *handle, 
                                      arm_tag_handler_t new)
{
        arm_tag_handler_t old;

        old = handle->arm_tag_handler;
        handle->arm_tag_handler = new;

        return old;
}


/**
 * raw1394_set_iso_handler - set isochronous packet handler
 * @new_h: pointer to new handler
 *
 * Sets the handler to be called when an isochronous packet is received to
 * @new_h and returns the old handler.  The default handler does nothing.
 *
 * In order to actually get iso packet events, receiving on a specific channel
 * first has to be enabled with raw1394_start_iso_rcv() and can be stopped again
 * with raw1394_stop_iso_rcv().
 **/
iso_handler_t raw1394_set_iso_handler(struct raw1394_handle *handle,
                                      unsigned int channel, iso_handler_t new)
{
        if (channel >= 64) {
                return (iso_handler_t)-1;
        }

        if (new == NULL) {
                iso_handler_t old = handle->iso_handler[channel];
                handle->iso_handler[channel] = NULL;
                return old;
        }

        if (handle->iso_handler[channel] != NULL) {
                return (iso_handler_t)-1;
        }

        handle->iso_handler[channel] = new;
        return NULL;
}

/**
 * raw1394_set_fcp_handler - set FCP handler
 * @new_h: pointer to new handler
 *
 * Sets the handler to be called when either FCP command or FCP response
 * registers get written to @new_h and returns the old handler.  The default
 * handler does nothing.
 *
 * In order to actually get FCP events, you have to enable it with
 * raw1394_start_fcp_listen() and can stop it with raw1394_stop_fcp_listen().
 **/
fcp_handler_t raw1394_set_fcp_handler(struct raw1394_handle *handle,
                                      fcp_handler_t new)
{
        fcp_handler_t old;

        old = handle->fcp_handler;
        handle->fcp_handler = new;

        return old;
}