hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
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
/*
 * Copyright (C) 2005,2006 Sebastian Smolorz
 *                         <Sebastian.Smolorz@stud.uni-hannover.de>
 *
 * Copyright (C) 2006 Wolfgang Grandegger <wg@grandegger.com>
 *
 *
 * Derived from RTnet project file include/stack/socket.h:
 *
 * Copyright (C) 1999       Lineo, Inc
 *               1999, 2002 David A. Schleef <ds@schleef.org>
 *               2002       Ulrich Marx <marx@kammer.uni-hannover.de>
 *               2003-2005  Jan Kiszka <jan.kiszka@web.de>
 *
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
#ifndef __RTCAN_SOCKET_H_
#define __RTCAN_SOCKET_H_
 
#include <rtdm/driver.h>
 
#include <rtdm/can.h>
 
 
 
/* This MUST BE 2^N */
#define RTCAN_RXBUF_SIZE          CONFIG_XENO_DRIVERS_CAN_RXBUF_SIZE
 
/* Size of timestamp */
#define RTCAN_TIMESTAMP_SIZE      sizeof(nanosecs_abs_t)
 
/* Bit in the can_dlc member of struct ring_buffer_frame used to indicate
 * whether a frame has got a timestamp or not */
#define RTCAN_HAS_TIMESTAMP       0x80
 
/* Mask for clearing bit RTCAN_HAS_TIMESTAMP */
#define RTCAN_HAS_NO_TIMESTAMP    0x7F
 
#define RTCAN_SOCK_UNBOUND        -1
#define RTCAN_FLIST_NO_FILTER     (struct rtcan_filter_list *)-1
#define rtcan_flist_no_filter(f)  ((f) == RTCAN_FLIST_NO_FILTER)
#define rtcan_sock_has_filter(s)  ((s)->flistlen > 0)
#define rtcan_sock_is_bound(s)    ((s)->flistlen >= 0)
 
/*
 *  Internal frame representation within the ring buffer of a
 *  struct rtcan_socket.
 *
 *  The data array is of arbitrary size when the frame is actually
 *  stored in a socket's ring buffer. The timestamp member exists if the
 *  socket was set to take timestamps (then it follows direcly after the
 *  arbitrary-sized data array), otherwise it does not exist.
 */
struct rtcan_rb_frame {
 
    /* CAN ID representation equal to struct can_frame */
    uint32_t            can_id;
 
    /* Interface index from which the frame originates */
    unsigned char       can_ifindex;
 
    /* DLC (between 0 and 15) and mark if frame has got a timestamp. The
     * existence of a timestamp is indicated by the RTCAN_HAS_TIMESTAMP
     * bit. */
    unsigned char       can_dlc;
 
    /* Data bytes */
    uint8_t             data[8];
 
    /* High precision timestamp indicating when the frame was received.
     * Exists when RTCAN_HAS_TIMESTAMP bit in can_dlc is set. */
    nanosecs_abs_t      timestamp;
 
} __attribute__ ((packed));
 
 
/* Size of struct rtcan_rb_frame without any data bytes and timestamp */
#define EMPTY_RB_FRAME_SIZE \
    sizeof(struct rtcan_rb_frame) - 8 - RTCAN_TIMESTAMP_SIZE
 
 
/*
 *  Wrapper structure around a struct rtcan_rb_frame with actual size
 *  of the frame.
 *
 *  This isn't really a socket buffer but only a sort of. It is constructed
 *  within the interrupt routine when a CAN frame is read from
 *  the controller. Then it's passed to the reception handler where only
 *  rb_frame finds its way to the sockets' ring buffers.
 */
struct rtcan_skb {
    /* Actual size of following rb_frame (without timestamp) */
    size_t                rb_frame_size;
    /* Frame to be stored in the sockets' ring buffers (as is) */
    struct rtcan_rb_frame rb_frame;
};
 
struct rtcan_filter_list {
    int flistlen;
    struct can_filter flist[1];
};
 
/*
 * Internal CAN socket structure.
 *
 * Every socket has an internal ring buffer for incoming messages. A message
 * is not stored as a struct can_frame (in order to save buffer space)
 * but as struct rtcan_rb_frame of arbitrary length depending on the
 * actual payload.
 */
struct rtcan_socket {
 
    struct list_head    socket_list;
 
    unsigned long    flags;
 
    /* Transmission timeout in ns. Protected by rtcan_socket_lock
     * in all socket structures. */
    nanosecs_rel_t      tx_timeout;
 
    /* Reception timeout in ns. Protected by rtcan_socket_lock
     * in all socket structures. */
    nanosecs_rel_t      rx_timeout;
 
 
    /* Begin of first frame data in the ring buffer. Protected by
     * rtcan_socket_lock in all socket structures. */
    int                 recv_head;
 
    /* End of last frame data in the ring buffer. I.e. position of first
     * free byte in the ring buffer. Protected by
     * rtcan_socket_lock in all socket structures. */
    int                 recv_tail;
 
    /* Ring buffer for incoming CAN frames. Protected by
     * rtcan_socket_lock in all socket structures. */
    unsigned char       recv_buf[RTCAN_RXBUF_SIZE];
 
    /* Semaphore for receivers and incoming messages */
    rtdm_sem_t          recv_sem;
 
 
    /* All senders waiting to be able to send
     * via this socket are queued here */
    struct list_head    tx_wait_head;
 
 
    /* Interface index the socket is bound to. Protected by
     * rtcan_recv_list_lock in all socket structures. */
    atomic_t            ifindex;
 
    /* Length of filter list. I.e. how many entries does this socket occupy in
     * the reception list. 0 if unbound. Protected by
     * rtcan_recv_list_lock in all socket structures. */
    int                 flistlen;
 
    uint32_t            err_mask;
 
    uint32_t            rx_buf_full;
 
    struct rtcan_filter_list *flist;
 
#ifdef CONFIG_XENO_DRIVERS_CAN_LOOPBACK
    int loopback;
#endif
};
 
 
 
/*
 *  Get the RTDM context from a struct rtcan_socket
 *
 *  @param[in] sock Pointer to socket structure
 *
 *  @return Pointer to a file descriptor of type struct rtdm_fd this socket
 *          belongs to
 */
/* FIXME: to be replaced with container_of */
static inline struct rtdm_fd *rtcan_socket_to_fd(struct rtcan_socket *sock)
{
    return rtdm_private_to_fd(sock);
}
 
/* Spinlock protecting the ring buffers and the timeouts of all
 * rtcan_sockets */
extern rtdm_lock_t rtcan_socket_lock;
extern struct list_head rtcan_socket_list;
 
extern void rtcan_socket_init(struct rtdm_fd *fd);
extern void rtcan_socket_cleanup(struct rtdm_fd *fd);
 
 
#endif  /* __RTCAN_SOCKET_H_ */