2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
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>
14 #define container_obj(layr) container_of(layr, struct cfsrvl, layer)
16 #define RFM_SEGMENTATION_BIT 0x01
17 #define RFM_PAYLOAD 0x00
18 #define RFM_CMD_BIT 0x80
19 #define RFM_FLOW_OFF 0x81
20 #define RFM_FLOW_ON 0x80
21 #define RFM_SET_PIN 0x82
22 #define RFM_CTRL_PKT_SIZE 1
24 static int cfrfml_receive(struct cflayer
*layr
, struct cfpkt
*pkt
);
25 static int cfrfml_transmit(struct cflayer
*layr
, struct cfpkt
*pkt
);
27 struct cflayer
*cfrfml_create(u8 channel_id
, struct dev_info
*dev_info
)
29 struct cfsrvl
*rfm
= kmalloc(sizeof(struct cfsrvl
), GFP_ATOMIC
);
32 pr_warning("CAIF: %s(): Out of memory\n", __func__
);
36 caif_assert(offsetof(struct cfsrvl
, layer
) == 0);
38 memset(rfm
, 0, sizeof(struct cfsrvl
));
39 cfsrvl_init(rfm
, channel_id
, dev_info
, false);
40 rfm
->layer
.receive
= cfrfml_receive
;
41 rfm
->layer
.transmit
= cfrfml_transmit
;
42 snprintf(rfm
->layer
.name
, CAIF_LAYER_NAME_SZ
, "rfm%d", channel_id
);
46 static int cfrfml_receive(struct cflayer
*layr
, struct cfpkt
*pkt
)
51 caif_assert(layr
->up
!= NULL
);
52 caif_assert(layr
->receive
!= NULL
);
55 * RFM is taking care of segmentation and stripping of
58 if (cfpkt_extr_head(pkt
, &tmp
, 1) < 0) {
59 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__
);
63 segmented
= tmp
& RFM_SEGMENTATION_BIT
;
64 caif_assert(!segmented
);
66 ret
= layr
->up
->receive(layr
->up
, pkt
);
70 static int cfrfml_transmit(struct cflayer
*layr
, struct cfpkt
*pkt
)
74 struct cfsrvl
*service
= container_obj(layr
);
76 caif_assert(layr
->dn
!= NULL
);
77 caif_assert(layr
->dn
->transmit
!= NULL
);
79 if (!cfsrvl_ready(service
, &ret
))
82 if (cfpkt_getlen(pkt
) > CAIF_MAX_PAYLOAD_SIZE
) {
83 pr_err("CAIF: %s():Packet too large - size=%d\n",
84 __func__
, cfpkt_getlen(pkt
));
87 if (cfpkt_add_head(pkt
, &tmp
, 1) < 0) {
88 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__
);
92 /* Add info for MUX-layer to route the packet out. */
93 cfpkt_info(pkt
)->channel_id
= service
->layer
.id
;
95 * To optimize alignment, we add up the size of CAIF header before
98 cfpkt_info(pkt
)->hdr_len
= 1;
99 cfpkt_info(pkt
)->dev_info
= &service
->dev_info
;
100 ret
= layr
->dn
->transmit(layr
->dn
, pkt
);
102 cfpkt_extr_head(pkt
, &tmp
, 1);