embox

Форк
0
227 строк · 5.0 Кб
1
/**
2
 * @file
3
 *
4
 * @author  Alex Kalmuk
5
 * @date    05.05.2015
6
 */
7

8
#include <assert.h>
9
#include <errno.h>
10
#include <string.h>
11
#include <util/math.h>
12
#include <util/log.h>
13

14
#include <net/l2/ethernet.h>
15
#include <net/netdevice.h>
16
#include <net/inetdevice.h>
17
#include <net/skbuff.h>
18
#include <net/l0/net_entry.h>
19
#include <net/l0/net_entry.h>
20
#include <drivers/usb/usb.h>
21
#include <drivers/usb/usb_driver.h>
22
#include <mem/sysmalloc.h>
23
#include <embox/unit.h>
24

25
#include <kernel/time/timer.h>
26

27
EMBOX_UNIT_INIT(usbnet_init);
28

29
#define USBNET_TIMER_FREQ 1
30

31
#define USBNET_IN_ENDP   1
32
#define USBNET_OUT_ENDP  2
33

34
static struct usb_driver usbnet_driver;
35
static const struct net_driver usbnet_drv_ops;
36

37
static void usbnet_timer_handler(struct sys_timer *tmr, void *param);
38

39
struct usbnet_priv {
40
	struct usb_interface *usbdev;
41
	/* Storage for incoming packet */
42
	char *data;
43
	/* Current position in packet */
44
	char *pdata;
45
	/* Timer for polling */
46
	struct sys_timer timer;
47

48
	struct net_device *nic;
49
};
50

51
static int usbnet_init(void) {
52
	return usb_driver_register(&usbnet_driver);
53
}
54

55
static void usbnet_rcv_notify(struct usb_request *req, void *arg) {
56
	struct usbnet_priv *nic_priv;
57
	struct net_device *nic;
58
	struct usb_endp *in_endp;
59

60
	nic_priv = (struct usbnet_priv *) req->endp->dev->current_config->usb_iface[2]->driver_data;
61
	assert(nic_priv);
62
	nic = nic_priv->nic;
63
	assert(nic);
64

65
	in_endp = nic_priv->usbdev->endpoints[USBNET_IN_ENDP];
66
	assert(in_endp);
67

68
	switch(req->req_stat) {
69
	case USB_REQ_NOERR:
70
		memcpy(nic_priv->pdata, req->buf, req->len);
71
		nic_priv->pdata += req->len;
72
		break;
73
	default:
74
		log_error("req error (req->req_stat=%d)\n", req->req_stat);
75
		return;
76
	}
77

78
	/* End of packet */
79
	if (req->actual_len < req->len) {
80
		struct sk_buff *skb;
81
		size_t len;
82

83
		len = nic_priv->pdata - nic_priv->data;
84
		skb = skb_alloc(len);
85
		if (!skb) {
86
			log_error("usbnet: skbuff allocation failed");
87
		} else {
88
			memcpy(skb->mac.raw, nic_priv->data, len);
89
			skb->dev = nic;
90
			netif_rx(skb);
91
		}
92

93
		/* Prepare for copying new packet */
94
		nic_priv->pdata = nic_priv->data;
95

96
		timer_init_start_msec(&nic_priv->timer, TIMER_ONESHOT,
97
				USBNET_TIMER_FREQ, usbnet_timer_handler, nic_priv);
98
	} else {
99
		/* Receive the next part of the packet */
100
		usb_endp_bulk(in_endp, usbnet_rcv_notify, NULL, nic_priv->pdata,
101
				in_endp->max_packet_size);
102
	}
103
}
104

105
static void usbnet_timer_handler(struct sys_timer *tmr, void *param) {
106
	struct usb_endp *in_endp;
107
	struct usbnet_priv *nic_priv = (struct usbnet_priv *) param;
108

109
	in_endp = nic_priv->usbdev->endpoints[USBNET_IN_ENDP];
110
	assert(in_endp);
111

112
	usb_endp_bulk(in_endp, usbnet_rcv_notify, NULL, nic_priv->pdata,
113
			in_endp->max_packet_size);
114
}
115

116
static int usbnet_probe(struct usb_interface *dev) {
117
	struct net_device *nic;
118
	struct usbnet_priv *nic_priv;
119
	int res;
120
	struct usb_interface *data_iface;
121

122
//	if (dev == dev->usb_dev->current_config->usb_iface[0]) {
123
//		return 0; /*control interface */
124
//	}
125

126
	data_iface = dev->usb_dev->current_config->usb_iface[2];
127

128
	assert(data_iface);
129

130
	/* Enable in/out DATA interface */
131
	if (usb_set_iface(dev->usb_dev, 1, 1) < 0) {
132
		res = -EINVAL;
133
		goto out_ret;
134
	}
135

136
	nic = (struct net_device *) etherdev_alloc(sizeof *nic_priv);
137
	if (!nic) {
138
		res = -ENOMEM;
139
		goto out_ret;
140
	}
141
	nic->drv_ops = &usbnet_drv_ops;
142
	nic_priv = netdev_priv(nic);
143
	nic_priv->usbdev = data_iface;
144
	nic_priv->nic = nic;
145
	nic_priv->data = nic_priv->pdata = sysmalloc(ETH_FRAME_LEN);
146
	if (!nic_priv->data) {
147
		res = -ENOMEM;
148
		goto out_free_nic;
149
	}
150
	data_iface->driver_data = nic_priv;
151

152
	res = inetdev_register_dev(nic);
153
	if (res < 0) {
154
		goto out_free_data;
155
	}
156

157
	res = timer_init_start_msec(&nic_priv->timer, TIMER_ONESHOT,
158
		USBNET_TIMER_FREQ, usbnet_timer_handler, nic_priv);
159
	if (res < 0) {
160
		goto out_free_data;
161
	}
162

163
	return 0;
164

165
out_free_data:
166
	sysfree(nic_priv->data);
167
out_free_nic:
168
	etherdev_free(nic);
169
out_ret:
170
	return res;
171
}
172

173
static void usbnet_disconnect(struct usb_interface *dev, void *data) {
174
}
175

176
static struct usb_device_id usbnet_id_table[] = {
177
	{ 2 /* CDC class */, 0x0525, 0xa4a2 },
178
	{ },
179
};
180

181
static void usbnet_send_notify_hnd(struct usb_request *req, void *arg) {
182
	if (arg) {
183
		skb_free((struct sk_buff *)arg);
184
	}
185
}
186

187
static int usbnet_xmit(struct net_device *dev, struct sk_buff *skb) {
188
	struct usb_endp *endp;
189
	struct usbnet_priv *priv = netdev_priv(dev);
190

191
	assert(priv);
192
	assert(priv->usbdev);
193

194
	endp = priv->usbdev->endpoints[USBNET_OUT_ENDP];
195
	assert(endp);
196

197
	log_debug("skb->len = %d\n", skb->len);
198

199
	if (usb_endp_bulk(endp, usbnet_send_notify_hnd, skb, skb->mac.raw, skb->len) != 0) {
200
		log_error("usb_endp_bulk failed");
201
		return -1;
202
	}
203

204
	if (skb->len % endp->max_packet_size == 0) {
205
		if (usb_endp_bulk(endp, usbnet_send_notify_hnd, NULL, NULL, 0) != 0) {
206
			log_error("usb_endp_bulk zero len packet failed");
207
			return -1;
208
		}
209
	}
210

211
	return 0;
212
}
213

214
static struct usb_driver usbnet_driver = {
215
	.probe = usbnet_probe,
216
	.disconnect = usbnet_disconnect,
217
	.id_table = usbnet_id_table,
218
};
219

220
static const struct net_driver usbnet_drv_ops = {
221
	.xmit = usbnet_xmit,
222
#if 0
223
	.start = usbnet_open,
224
	.stop = usbnet_stop,
225
	.set_macaddr = usbnet_set_mac_address
226
#endif
227
};
228

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.