Skip to content

Commit b482cd2

Browse files
Sjur Braendelanddavem330
authored andcommitted
net-caif: add CAIF core protocol stack
CAIF generic protocol implementation. This layer is somewhat generic in order to be able to use and test it outside the Linux Kernel. cfctrl.c - CAIF control protocol layer cfdbgl.c - CAIF debug protocol layer cfdgml.c - CAIF datagram protocol layer cffrml.c - CAIF framing protocol layer cfmuxl.c - CAIF mux protocol layer cfrfml.c - CAIF remote file manager protocol layer cfserl.c - CAIF serial (fragmentation) protocol layer cfsrvl.c - CAIF generic service layer functions cfutill.c - CAIF utility protocol layer cfveil.c - CAIF AT protocol layer cfvidl.c - CAIF video protocol layer Signed-off-by: Sjur Braendeland <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2721c5b commit b482cd2

File tree

11 files changed

+1981
-0
lines changed

11 files changed

+1981
-0
lines changed

net/caif/cfctrl.c

Lines changed: 664 additions & 0 deletions
Large diffs are not rendered by default.

net/caif/cfdbgl.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (C) ST-Ericsson AB 2010
3+
* Author: Sjur Brendeland/[email protected]
4+
* License terms: GNU General Public License (GPL) version 2
5+
*/
6+
7+
#include <linux/stddef.h>
8+
#include <linux/slab.h>
9+
#include <net/caif/caif_layer.h>
10+
#include <net/caif/cfsrvl.h>
11+
#include <net/caif/cfpkt.h>
12+
13+
static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt);
14+
static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt);
15+
16+
struct cflayer *cfdbgl_create(u8 channel_id, struct dev_info *dev_info)
17+
{
18+
struct cfsrvl *dbg = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
19+
if (!dbg) {
20+
pr_warning("CAIF: %s(): Out of memory\n", __func__);
21+
return NULL;
22+
}
23+
caif_assert(offsetof(struct cfsrvl, layer) == 0);
24+
memset(dbg, 0, sizeof(struct cfsrvl));
25+
cfsrvl_init(dbg, channel_id, dev_info);
26+
dbg->layer.receive = cfdbgl_receive;
27+
dbg->layer.transmit = cfdbgl_transmit;
28+
snprintf(dbg->layer.name, CAIF_LAYER_NAME_SZ - 1, "dbg%d", channel_id);
29+
return &dbg->layer;
30+
}
31+
32+
static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt)
33+
{
34+
return layr->up->receive(layr->up, pkt);
35+
}
36+
37+
static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt)
38+
{
39+
return layr->dn->transmit(layr->dn, pkt);
40+
}

net/caif/cfdgml.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright (C) ST-Ericsson AB 2010
3+
* Author: Sjur Brendeland/[email protected]
4+
* License terms: GNU General Public License (GPL) version 2
5+
*/
6+
7+
#include <linux/stddef.h>
8+
#include <linux/spinlock.h>
9+
#include <linux/slab.h>
10+
#include <net/caif/caif_layer.h>
11+
#include <net/caif/cfsrvl.h>
12+
#include <net/caif/cfpkt.h>
13+
14+
#define container_obj(layr) ((struct cfsrvl *) layr)
15+
16+
#define DGM_CMD_BIT 0x80
17+
#define DGM_FLOW_OFF 0x81
18+
#define DGM_FLOW_ON 0x80
19+
#define DGM_CTRL_PKT_SIZE 1
20+
21+
static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt);
22+
static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt);
23+
24+
struct cflayer *cfdgml_create(u8 channel_id, struct dev_info *dev_info)
25+
{
26+
struct cfsrvl *dgm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC);
27+
if (!dgm) {
28+
pr_warning("CAIF: %s(): Out of memory\n", __func__);
29+
return NULL;
30+
}
31+
caif_assert(offsetof(struct cfsrvl, layer) == 0);
32+
memset(dgm, 0, sizeof(struct cfsrvl));
33+
cfsrvl_init(dgm, channel_id, dev_info);
34+
dgm->layer.receive = cfdgml_receive;
35+
dgm->layer.transmit = cfdgml_transmit;
36+
snprintf(dgm->layer.name, CAIF_LAYER_NAME_SZ - 1, "dgm%d", channel_id);
37+
dgm->layer.name[CAIF_LAYER_NAME_SZ - 1] = '\0';
38+
return &dgm->layer;
39+
}
40+
41+
static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt)
42+
{
43+
u8 cmd = -1;
44+
u8 dgmhdr[3];
45+
int ret;
46+
caif_assert(layr->up != NULL);
47+
caif_assert(layr->receive != NULL);
48+
caif_assert(layr->ctrlcmd != NULL);
49+
50+
if (cfpkt_extr_head(pkt, &cmd, 1) < 0) {
51+
pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
52+
cfpkt_destroy(pkt);
53+
return -EPROTO;
54+
}
55+
56+
if ((cmd & DGM_CMD_BIT) == 0) {
57+
if (cfpkt_extr_head(pkt, &dgmhdr, 3) < 0) {
58+
pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
59+
cfpkt_destroy(pkt);
60+
return -EPROTO;
61+
}
62+
ret = layr->up->receive(layr->up, pkt);
63+
return ret;
64+
}
65+
66+
switch (cmd) {
67+
case DGM_FLOW_OFF: /* FLOW OFF */
68+
layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_OFF_IND, 0);
69+
cfpkt_destroy(pkt);
70+
return 0;
71+
case DGM_FLOW_ON: /* FLOW ON */
72+
layr->ctrlcmd(layr, CAIF_CTRLCMD_FLOW_ON_IND, 0);
73+
cfpkt_destroy(pkt);
74+
return 0;
75+
default:
76+
cfpkt_destroy(pkt);
77+
pr_info("CAIF: %s(): Unknown datagram control %d (0x%x)\n",
78+
__func__, cmd, cmd);
79+
return -EPROTO;
80+
}
81+
}
82+
83+
static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt)
84+
{
85+
u32 zero = 0;
86+
struct caif_payload_info *info;
87+
struct cfsrvl *service = container_obj(layr);
88+
int ret;
89+
if (!cfsrvl_ready(service, &ret))
90+
return ret;
91+
92+
cfpkt_add_head(pkt, &zero, 4);
93+
94+
/* Add info for MUX-layer to route the packet out. */
95+
info = cfpkt_info(pkt);
96+
info->channel_id = service->layer.id;
97+
/* To optimize alignment, we add up the size of CAIF header
98+
* before payload.
99+
*/
100+
info->hdr_len = 4;
101+
info->dev_info = &service->dev_info;
102+
ret = layr->dn->transmit(layr->dn, pkt);
103+
if (ret < 0) {
104+
u32 tmp32;
105+
cfpkt_extr_head(pkt, &tmp32, 4);
106+
}
107+
return ret;
108+
}

net/caif/cffrml.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* CAIF Framing Layer.
3+
*
4+
* Copyright (C) ST-Ericsson AB 2010
5+
* Author: Sjur Brendeland/[email protected]
6+
* License terms: GNU General Public License (GPL) version 2
7+
*/
8+
9+
#include <linux/stddef.h>
10+
#include <linux/spinlock.h>
11+
#include <linux/slab.h>
12+
#include <linux/crc-ccitt.h>
13+
#include <net/caif/caif_layer.h>
14+
#include <net/caif/cfpkt.h>
15+
#include <net/caif/cffrml.h>
16+
17+
#define container_obj(layr) container_of(layr, struct cffrml, layer)
18+
19+
struct cffrml {
20+
struct cflayer layer;
21+
bool dofcs; /* !< FCS active */
22+
};
23+
24+
static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
25+
static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt);
26+
static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
27+
int phyid);
28+
29+
static u32 cffrml_rcv_error;
30+
static u32 cffrml_rcv_checsum_error;
31+
struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
32+
{
33+
struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC);
34+
if (!this) {
35+
pr_warning("CAIF: %s(): Out of memory\n", __func__);
36+
return NULL;
37+
}
38+
caif_assert(offsetof(struct cffrml, layer) == 0);
39+
40+
memset(this, 0, sizeof(struct cflayer));
41+
this->layer.receive = cffrml_receive;
42+
this->layer.transmit = cffrml_transmit;
43+
this->layer.ctrlcmd = cffrml_ctrlcmd;
44+
snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "frm%d", phyid);
45+
this->dofcs = use_fcs;
46+
this->layer.id = phyid;
47+
return (struct cflayer *) this;
48+
}
49+
50+
void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up)
51+
{
52+
this->up = up;
53+
}
54+
55+
void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn)
56+
{
57+
this->dn = dn;
58+
}
59+
60+
static u16 cffrml_checksum(u16 chks, void *buf, u16 len)
61+
{
62+
/* FIXME: FCS should be moved to glue in order to use OS-Specific
63+
* solutions
64+
*/
65+
return crc_ccitt(chks, buf, len);
66+
}
67+
68+
static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
69+
{
70+
u16 tmp;
71+
u16 len;
72+
u16 hdrchks;
73+
u16 pktchks;
74+
struct cffrml *this;
75+
this = container_obj(layr);
76+
77+
cfpkt_extr_head(pkt, &tmp, 2);
78+
len = le16_to_cpu(tmp);
79+
80+
/* Subtract for FCS on length if FCS is not used. */
81+
if (!this->dofcs)
82+
len -= 2;
83+
84+
if (cfpkt_setlen(pkt, len) < 0) {
85+
++cffrml_rcv_error;
86+
pr_err("CAIF: %s():Framing length error (%d)\n", __func__, len);
87+
cfpkt_destroy(pkt);
88+
return -EPROTO;
89+
}
90+
/*
91+
* Don't do extract if FCS is false, rather do setlen - then we don't
92+
* get a cache-miss.
93+
*/
94+
if (this->dofcs) {
95+
cfpkt_extr_trail(pkt, &tmp, 2);
96+
hdrchks = le16_to_cpu(tmp);
97+
pktchks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
98+
if (pktchks != hdrchks) {
99+
cfpkt_add_trail(pkt, &tmp, 2);
100+
++cffrml_rcv_error;
101+
++cffrml_rcv_checsum_error;
102+
pr_info("CAIF: %s(): Frame checksum error "
103+
"(0x%x != 0x%x)\n", __func__, hdrchks, pktchks);
104+
return -EILSEQ;
105+
}
106+
}
107+
if (cfpkt_erroneous(pkt)) {
108+
++cffrml_rcv_error;
109+
pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
110+
cfpkt_destroy(pkt);
111+
return -EPROTO;
112+
}
113+
return layr->up->receive(layr->up, pkt);
114+
}
115+
116+
static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
117+
{
118+
int tmp;
119+
u16 chks;
120+
u16 len;
121+
int ret;
122+
struct cffrml *this = container_obj(layr);
123+
if (this->dofcs) {
124+
chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
125+
tmp = cpu_to_le16(chks);
126+
cfpkt_add_trail(pkt, &tmp, 2);
127+
} else {
128+
cfpkt_pad_trail(pkt, 2);
129+
}
130+
len = cfpkt_getlen(pkt);
131+
tmp = cpu_to_le16(len);
132+
cfpkt_add_head(pkt, &tmp, 2);
133+
cfpkt_info(pkt)->hdr_len += 2;
134+
if (cfpkt_erroneous(pkt)) {
135+
pr_err("CAIF: %s(): Packet is erroneous!\n", __func__);
136+
return -EPROTO;
137+
}
138+
ret = layr->dn->transmit(layr->dn, pkt);
139+
if (ret < 0) {
140+
/* Remove header on faulty packet. */
141+
cfpkt_extr_head(pkt, &tmp, 2);
142+
}
143+
return ret;
144+
}
145+
146+
static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
147+
int phyid)
148+
{
149+
if (layr->up->ctrlcmd)
150+
layr->up->ctrlcmd(layr->up, ctrl, layr->id);
151+
}

0 commit comments

Comments
 (0)