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
);
26 static int cfservl_modemcmd(struct cflayer
*layr
, enum caif_modemcmd ctrl
);
28 struct cflayer
*cfrfml_create(u8 channel_id
, struct dev_info
*dev_info
)
30 struct cfsrvl
*rfm
= kmalloc(sizeof(struct cfsrvl
), GFP_ATOMIC
);
32 pr_warning("CAIF: %s(): Out of memory\n", __func__
);
35 caif_assert(offsetof(struct cfsrvl
, layer
) == 0);
36 memset(rfm
, 0, sizeof(struct cfsrvl
));
37 cfsrvl_init(rfm
, channel_id
, dev_info
);
38 rfm
->layer
.modemcmd
= cfservl_modemcmd
;
39 rfm
->layer
.receive
= cfrfml_receive
;
40 rfm
->layer
.transmit
= cfrfml_transmit
;
41 snprintf(rfm
->layer
.name
, CAIF_LAYER_NAME_SZ
, "rfm%d", channel_id
);
45 static int cfservl_modemcmd(struct cflayer
*layr
, enum caif_modemcmd ctrl
)
50 static int cfrfml_receive(struct cflayer
*layr
, struct cfpkt
*pkt
)
55 caif_assert(layr
->up
!= NULL
);
56 caif_assert(layr
->receive
!= NULL
);
59 * RFM is taking care of segmentation and stripping of
62 if (cfpkt_extr_head(pkt
, &tmp
, 1) < 0) {
63 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__
);
67 segmented
= tmp
& RFM_SEGMENTATION_BIT
;
68 caif_assert(!segmented
);
70 ret
= layr
->up
->receive(layr
->up
, pkt
);
74 static int cfrfml_transmit(struct cflayer
*layr
, struct cfpkt
*pkt
)
78 struct cfsrvl
*service
= container_obj(layr
);
80 caif_assert(layr
->dn
!= NULL
);
81 caif_assert(layr
->dn
->transmit
!= NULL
);
83 if (!cfsrvl_ready(service
, &ret
))
86 if (!cfpkt_getlen(pkt
) > CAIF_MAX_PAYLOAD_SIZE
) {
87 pr_err("CAIF: %s():Packet too large - size=%d\n",
88 __func__
, cfpkt_getlen(pkt
));
91 if (cfpkt_add_head(pkt
, &tmp
, 1) < 0) {
92 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__
);
96 /* Add info for MUX-layer to route the packet out. */
97 cfpkt_info(pkt
)->channel_id
= service
->layer
.id
;
99 * To optimize alignment, we add up the size of CAIF header before
102 cfpkt_info(pkt
)->hdr_len
= 1;
103 cfpkt_info(pkt
)->dev_info
= &service
->dev_info
;
104 ret
= layr
->dn
->transmit(layr
->dn
, pkt
);
106 cfpkt_extr_head(pkt
, &tmp
, 1);