summaryrefslogtreecommitdiff
path: root/net/mhi/l3phonet.c
blob: 8de7471296dbec435dd6d5591bdb2e02ed59ffd1 (plain)
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
/*
 * File: l3phonet.c
 *
 * L2 PHONET channel to AF_PHONET binding.
 *
 * Copyright (C) 2011 Renesas Mobile Corporation. All rights reserved.
 *
 * Author: Petri To Mattila <petri.to.mattila@renesasmobile.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/mhi.h>
#include <linux/l2mux.h>


/* Functions */

static int
mhi_pn_netif_rx(struct sk_buff *skb, struct net_device *dev)
{
	/* Set Protocol Family */
	skb->protocol = htons(ETH_P_PHONET);

	/* Remove L2MUX header and Phonet media byte */
	skb_pull(skb, L2MUX_HDR_SIZE + 1);

	/* Pass upwards to the Procotol Family */
	return netif_rx(skb);
}

static int
mhi_pn_netif_tx(struct sk_buff *skb, struct net_device *dev)
{
	struct l2muxhdr *l2hdr;
	int l3len;
	u8  *ptr;

	/* Add media byte */
	ptr = skb_push(skb, 1);

	/* Set media byte */
	ptr[0] = dev->dev_addr[0];

	/* L3 length */
	l3len = skb->len;

	/* Add L2MUX header */
	skb_push(skb, L2MUX_HDR_SIZE);

	/* Mac header starts here */
	skb_reset_mac_header(skb);

	/* L2MUX header pointer */
	l2hdr = l2mux_hdr(skb);

	/* L3 Proto ID */
	l2mux_set_proto(l2hdr, MHI_L3_PHONET);

	/* L3 payload length */
	l2mux_set_length(l2hdr, l3len);

	return 0;
}


/* Module registration */

int __init mhi_pn_init(void)
{
	int err;

	err = l2mux_netif_rx_register(MHI_L3_PHONET, mhi_pn_netif_rx);
	if (err)
		goto err1;

	err = l2mux_netif_tx_register(ETH_P_PHONET, mhi_pn_netif_tx);
	if (err)
		goto err2;

	return 0;

err2:
	l2mux_netif_rx_unregister(MHI_L3_PHONET);
err1:
	return err;
}

void __exit mhi_pn_exit(void)
{
	l2mux_netif_rx_unregister(MHI_L3_PHONET);
	l2mux_netif_tx_unregister(ETH_P_PHONET);
}


module_init(mhi_pn_init);
module_exit(mhi_pn_exit);

MODULE_AUTHOR("Petri Mattila <petri.to.mattila@renesasmobile.com>");
MODULE_DESCRIPTION("MHI Phonet protocol family bridge");
MODULE_LICENSE("GPL");