• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/usb/gadget/
1/*
2 * f_phonet.c -- USB CDC Phonet function
3 *
4 * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
5 *
6 * Author: R��mi Denis-Courmont
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ��See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23#include <linux/slab.h>
24#include <linux/kernel.h>
25#include <linux/device.h>
26
27#include <linux/netdevice.h>
28#include <linux/if_ether.h>
29#include <linux/if_phonet.h>
30#include <linux/if_arp.h>
31
32#include <linux/usb/ch9.h>
33#include <linux/usb/cdc.h>
34#include <linux/usb/composite.h>
35
36#include "u_phonet.h"
37
38#define PN_MEDIA_USB	0x1B
39#define MAXPACKET	512
40#if (PAGE_SIZE % MAXPACKET)
41#error MAXPACKET must divide PAGE_SIZE!
42#endif
43
44/*-------------------------------------------------------------------------*/
45
46struct phonet_port {
47	struct f_phonet			*usb;
48	spinlock_t			lock;
49};
50
51struct f_phonet {
52	struct usb_function		function;
53	struct {
54		struct sk_buff		*skb;
55		spinlock_t		lock;
56	} rx;
57	struct net_device		*dev;
58	struct usb_ep			*in_ep, *out_ep;
59
60	struct usb_request		*in_req;
61	struct usb_request		*out_reqv[0];
62};
63
64static int phonet_rxq_size = 17;
65
66static inline struct f_phonet *func_to_pn(struct usb_function *f)
67{
68	return container_of(f, struct f_phonet, function);
69}
70
71/*-------------------------------------------------------------------------*/
72
73#define USB_CDC_SUBCLASS_PHONET	0xfe
74#define USB_CDC_PHONET_TYPE	0xab
75
76static struct usb_interface_descriptor
77pn_control_intf_desc = {
78	.bLength =		sizeof pn_control_intf_desc,
79	.bDescriptorType =	USB_DT_INTERFACE,
80
81	/* .bInterfaceNumber =	DYNAMIC, */
82	.bInterfaceClass =	USB_CLASS_COMM,
83	.bInterfaceSubClass =	USB_CDC_SUBCLASS_PHONET,
84};
85
86static const struct usb_cdc_header_desc
87pn_header_desc = {
88	.bLength =		sizeof pn_header_desc,
89	.bDescriptorType =	USB_DT_CS_INTERFACE,
90	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
91	.bcdCDC =		cpu_to_le16(0x0110),
92};
93
94static const struct usb_cdc_header_desc
95pn_phonet_desc = {
96	.bLength =		sizeof pn_phonet_desc,
97	.bDescriptorType =	USB_DT_CS_INTERFACE,
98	.bDescriptorSubType =	USB_CDC_PHONET_TYPE,
99	.bcdCDC =		cpu_to_le16(0x1505), /* ??? */
100};
101
102static struct usb_cdc_union_desc
103pn_union_desc = {
104	.bLength =		sizeof pn_union_desc,
105	.bDescriptorType =	USB_DT_CS_INTERFACE,
106	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
107
108	/* .bMasterInterface0 =	DYNAMIC, */
109	/* .bSlaveInterface0 =	DYNAMIC, */
110};
111
112static struct usb_interface_descriptor
113pn_data_nop_intf_desc = {
114	.bLength =		sizeof pn_data_nop_intf_desc,
115	.bDescriptorType =	USB_DT_INTERFACE,
116
117	/* .bInterfaceNumber =	DYNAMIC, */
118	.bAlternateSetting =	0,
119	.bNumEndpoints =	0,
120	.bInterfaceClass =	USB_CLASS_CDC_DATA,
121};
122
123static struct usb_interface_descriptor
124pn_data_intf_desc = {
125	.bLength =		sizeof pn_data_intf_desc,
126	.bDescriptorType =	USB_DT_INTERFACE,
127
128	/* .bInterfaceNumber =	DYNAMIC, */
129	.bAlternateSetting =	1,
130	.bNumEndpoints =	2,
131	.bInterfaceClass =	USB_CLASS_CDC_DATA,
132};
133
134static struct usb_endpoint_descriptor
135pn_fs_sink_desc = {
136	.bLength =		USB_DT_ENDPOINT_SIZE,
137	.bDescriptorType =	USB_DT_ENDPOINT,
138
139	.bEndpointAddress =	USB_DIR_OUT,
140	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
141};
142
143static struct usb_endpoint_descriptor
144pn_hs_sink_desc = {
145	.bLength =		USB_DT_ENDPOINT_SIZE,
146	.bDescriptorType =	USB_DT_ENDPOINT,
147
148	.bEndpointAddress =	USB_DIR_OUT,
149	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
150	.wMaxPacketSize =	cpu_to_le16(MAXPACKET),
151};
152
153static struct usb_endpoint_descriptor
154pn_fs_source_desc = {
155	.bLength =		USB_DT_ENDPOINT_SIZE,
156	.bDescriptorType =	USB_DT_ENDPOINT,
157
158	.bEndpointAddress =	USB_DIR_IN,
159	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
160};
161
162static struct usb_endpoint_descriptor
163pn_hs_source_desc = {
164	.bLength =		USB_DT_ENDPOINT_SIZE,
165	.bDescriptorType =	USB_DT_ENDPOINT,
166
167	.bEndpointAddress =	USB_DIR_IN,
168	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
169	.wMaxPacketSize =	cpu_to_le16(512),
170};
171
172static struct usb_descriptor_header *fs_pn_function[] = {
173	(struct usb_descriptor_header *) &pn_control_intf_desc,
174	(struct usb_descriptor_header *) &pn_header_desc,
175	(struct usb_descriptor_header *) &pn_phonet_desc,
176	(struct usb_descriptor_header *) &pn_union_desc,
177	(struct usb_descriptor_header *) &pn_data_nop_intf_desc,
178	(struct usb_descriptor_header *) &pn_data_intf_desc,
179	(struct usb_descriptor_header *) &pn_fs_sink_desc,
180	(struct usb_descriptor_header *) &pn_fs_source_desc,
181	NULL,
182};
183
184static struct usb_descriptor_header *hs_pn_function[] = {
185	(struct usb_descriptor_header *) &pn_control_intf_desc,
186	(struct usb_descriptor_header *) &pn_header_desc,
187	(struct usb_descriptor_header *) &pn_phonet_desc,
188	(struct usb_descriptor_header *) &pn_union_desc,
189	(struct usb_descriptor_header *) &pn_data_nop_intf_desc,
190	(struct usb_descriptor_header *) &pn_data_intf_desc,
191	(struct usb_descriptor_header *) &pn_hs_sink_desc,
192	(struct usb_descriptor_header *) &pn_hs_source_desc,
193	NULL,
194};
195
196/*-------------------------------------------------------------------------*/
197
198static int pn_net_open(struct net_device *dev)
199{
200	netif_wake_queue(dev);
201	return 0;
202}
203
204static int pn_net_close(struct net_device *dev)
205{
206	netif_stop_queue(dev);
207	return 0;
208}
209
210static void pn_tx_complete(struct usb_ep *ep, struct usb_request *req)
211{
212	struct f_phonet *fp = ep->driver_data;
213	struct net_device *dev = fp->dev;
214	struct sk_buff *skb = req->context;
215
216	switch (req->status) {
217	case 0:
218		dev->stats.tx_packets++;
219		dev->stats.tx_bytes += skb->len;
220		break;
221
222	case -ESHUTDOWN: /* disconnected */
223	case -ECONNRESET: /* disabled */
224		dev->stats.tx_aborted_errors++;
225	default:
226		dev->stats.tx_errors++;
227	}
228
229	dev_kfree_skb_any(skb);
230	netif_wake_queue(dev);
231}
232
233static int pn_net_xmit(struct sk_buff *skb, struct net_device *dev)
234{
235	struct phonet_port *port = netdev_priv(dev);
236	struct f_phonet *fp;
237	struct usb_request *req;
238	unsigned long flags;
239
240	if (skb->protocol != htons(ETH_P_PHONET))
241		goto out;
242
243	spin_lock_irqsave(&port->lock, flags);
244	fp = port->usb;
245	if (unlikely(!fp)) /* race with carrier loss */
246		goto out_unlock;
247
248	req = fp->in_req;
249	req->buf = skb->data;
250	req->length = skb->len;
251	req->complete = pn_tx_complete;
252	req->zero = 1;
253	req->context = skb;
254
255	if (unlikely(usb_ep_queue(fp->in_ep, req, GFP_ATOMIC)))
256		goto out_unlock;
257
258	netif_stop_queue(dev);
259	skb = NULL;
260
261out_unlock:
262	spin_unlock_irqrestore(&port->lock, flags);
263out:
264	if (unlikely(skb)) {
265		dev_kfree_skb(skb);
266		dev->stats.tx_dropped++;
267	}
268	return NETDEV_TX_OK;
269}
270
271static int pn_net_mtu(struct net_device *dev, int new_mtu)
272{
273	if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
274		return -EINVAL;
275	dev->mtu = new_mtu;
276	return 0;
277}
278
279static const struct net_device_ops pn_netdev_ops = {
280	.ndo_open	= pn_net_open,
281	.ndo_stop	= pn_net_close,
282	.ndo_start_xmit	= pn_net_xmit,
283	.ndo_change_mtu	= pn_net_mtu,
284};
285
286static void pn_net_setup(struct net_device *dev)
287{
288	dev->features		= 0;
289	dev->type		= ARPHRD_PHONET;
290	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
291	dev->mtu		= PHONET_DEV_MTU;
292	dev->hard_header_len	= 1;
293	dev->dev_addr[0]	= PN_MEDIA_USB;
294	dev->addr_len		= 1;
295	dev->tx_queue_len	= 1;
296
297	dev->netdev_ops		= &pn_netdev_ops;
298	dev->destructor		= free_netdev;
299	dev->header_ops		= &phonet_header_ops;
300}
301
302/*-------------------------------------------------------------------------*/
303
304/*
305 * Queue buffer for data from the host
306 */
307static int
308pn_rx_submit(struct f_phonet *fp, struct usb_request *req, gfp_t gfp_flags)
309{
310	struct net_device *dev = fp->dev;
311	struct page *page;
312	int err;
313
314	page = __netdev_alloc_page(dev, gfp_flags);
315	if (!page)
316		return -ENOMEM;
317
318	req->buf = page_address(page);
319	req->length = PAGE_SIZE;
320	req->context = page;
321
322	err = usb_ep_queue(fp->out_ep, req, gfp_flags);
323	if (unlikely(err))
324		netdev_free_page(dev, page);
325	return err;
326}
327
328static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)
329{
330	struct f_phonet *fp = ep->driver_data;
331	struct net_device *dev = fp->dev;
332	struct page *page = req->context;
333	struct sk_buff *skb;
334	unsigned long flags;
335	int status = req->status;
336
337	switch (status) {
338	case 0:
339		spin_lock_irqsave(&fp->rx.lock, flags);
340		skb = fp->rx.skb;
341		if (!skb)
342			skb = fp->rx.skb = netdev_alloc_skb(dev, 12);
343		if (req->actual < req->length) /* Last fragment */
344			fp->rx.skb = NULL;
345		spin_unlock_irqrestore(&fp->rx.lock, flags);
346
347		if (unlikely(!skb))
348			break;
349		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 0,
350				req->actual);
351		page = NULL;
352
353		if (req->actual < req->length) { /* Last fragment */
354			skb->protocol = htons(ETH_P_PHONET);
355			skb_reset_mac_header(skb);
356			pskb_pull(skb, 1);
357			skb->dev = dev;
358			dev->stats.rx_packets++;
359			dev->stats.rx_bytes += skb->len;
360
361			netif_rx(skb);
362		}
363		break;
364
365	/* Do not resubmit in these cases: */
366	case -ESHUTDOWN: /* disconnect */
367	case -ECONNABORTED: /* hw reset */
368	case -ECONNRESET: /* dequeued (unlink or netif down) */
369		req = NULL;
370		break;
371
372	/* Do resubmit in these cases: */
373	case -EOVERFLOW: /* request buffer overflow */
374		dev->stats.rx_over_errors++;
375	default:
376		dev->stats.rx_errors++;
377		break;
378	}
379
380	if (page)
381		netdev_free_page(dev, page);
382	if (req)
383		pn_rx_submit(fp, req, GFP_ATOMIC);
384}
385
386/*-------------------------------------------------------------------------*/
387
388static void __pn_reset(struct usb_function *f)
389{
390	struct f_phonet *fp = func_to_pn(f);
391	struct net_device *dev = fp->dev;
392	struct phonet_port *port = netdev_priv(dev);
393
394	netif_carrier_off(dev);
395	port->usb = NULL;
396
397	usb_ep_disable(fp->out_ep);
398	usb_ep_disable(fp->in_ep);
399	if (fp->rx.skb) {
400		dev_kfree_skb_irq(fp->rx.skb);
401		fp->rx.skb = NULL;
402	}
403}
404
405static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
406{
407	struct f_phonet *fp = func_to_pn(f);
408	struct usb_gadget *gadget = fp->function.config->cdev->gadget;
409
410	if (intf == pn_control_intf_desc.bInterfaceNumber)
411		/* control interface, no altsetting */
412		return (alt > 0) ? -EINVAL : 0;
413
414	if (intf == pn_data_intf_desc.bInterfaceNumber) {
415		struct net_device *dev = fp->dev;
416		struct phonet_port *port = netdev_priv(dev);
417
418		/* data intf (0: inactive, 1: active) */
419		if (alt > 1)
420			return -EINVAL;
421
422		spin_lock(&port->lock);
423		__pn_reset(f);
424		if (alt == 1) {
425			struct usb_endpoint_descriptor *out, *in;
426			int i;
427
428			out = ep_choose(gadget,
429					&pn_hs_sink_desc,
430					&pn_fs_sink_desc);
431			in = ep_choose(gadget,
432					&pn_hs_source_desc,
433					&pn_fs_source_desc);
434			usb_ep_enable(fp->out_ep, out);
435			usb_ep_enable(fp->in_ep, in);
436
437			port->usb = fp;
438			fp->out_ep->driver_data = fp;
439			fp->in_ep->driver_data = fp;
440
441			netif_carrier_on(dev);
442			for (i = 0; i < phonet_rxq_size; i++)
443				pn_rx_submit(fp, fp->out_reqv[i], GFP_ATOMIC);
444		}
445		spin_unlock(&port->lock);
446		return 0;
447	}
448
449	return -EINVAL;
450}
451
452static int pn_get_alt(struct usb_function *f, unsigned intf)
453{
454	struct f_phonet *fp = func_to_pn(f);
455
456	if (intf == pn_control_intf_desc.bInterfaceNumber)
457		return 0;
458
459	if (intf == pn_data_intf_desc.bInterfaceNumber) {
460		struct phonet_port *port = netdev_priv(fp->dev);
461		u8 alt;
462
463		spin_lock(&port->lock);
464		alt = port->usb != NULL;
465		spin_unlock(&port->lock);
466		return alt;
467	}
468
469	return -EINVAL;
470}
471
472static void pn_disconnect(struct usb_function *f)
473{
474	struct f_phonet *fp = func_to_pn(f);
475	struct phonet_port *port = netdev_priv(fp->dev);
476	unsigned long flags;
477
478	/* remain disabled until set_alt */
479	spin_lock_irqsave(&port->lock, flags);
480	__pn_reset(f);
481	spin_unlock_irqrestore(&port->lock, flags);
482}
483
484/*-------------------------------------------------------------------------*/
485
486static __init
487int pn_bind(struct usb_configuration *c, struct usb_function *f)
488{
489	struct usb_composite_dev *cdev = c->cdev;
490	struct usb_gadget *gadget = cdev->gadget;
491	struct f_phonet *fp = func_to_pn(f);
492	struct usb_ep *ep;
493	int status, i;
494
495	/* Reserve interface IDs */
496	status = usb_interface_id(c, f);
497	if (status < 0)
498		goto err;
499	pn_control_intf_desc.bInterfaceNumber = status;
500	pn_union_desc.bMasterInterface0 = status;
501
502	status = usb_interface_id(c, f);
503	if (status < 0)
504		goto err;
505	pn_data_nop_intf_desc.bInterfaceNumber = status;
506	pn_data_intf_desc.bInterfaceNumber = status;
507	pn_union_desc.bSlaveInterface0 = status;
508
509	/* Reserve endpoints */
510	status = -ENODEV;
511	ep = usb_ep_autoconfig(gadget, &pn_fs_sink_desc);
512	if (!ep)
513		goto err;
514	fp->out_ep = ep;
515	ep->driver_data = fp; /* Claim */
516
517	ep = usb_ep_autoconfig(gadget, &pn_fs_source_desc);
518	if (!ep)
519		goto err;
520	fp->in_ep = ep;
521	ep->driver_data = fp; /* Claim */
522
523	pn_hs_sink_desc.bEndpointAddress =
524		pn_fs_sink_desc.bEndpointAddress;
525	pn_hs_source_desc.bEndpointAddress =
526		pn_fs_source_desc.bEndpointAddress;
527
528	/* Do not try to bind Phonet twice... */
529	fp->function.descriptors = fs_pn_function;
530	fp->function.hs_descriptors = hs_pn_function;
531
532	/* Incoming USB requests */
533	status = -ENOMEM;
534	for (i = 0; i < phonet_rxq_size; i++) {
535		struct usb_request *req;
536
537		req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL);
538		if (!req)
539			goto err;
540
541		req->complete = pn_rx_complete;
542		fp->out_reqv[i] = req;
543	}
544
545	/* Outgoing USB requests */
546	fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL);
547	if (!fp->in_req)
548		goto err;
549
550	INFO(cdev, "USB CDC Phonet function\n");
551	INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name,
552		fp->out_ep->name, fp->in_ep->name);
553	return 0;
554
555err:
556	if (fp->out_ep)
557		fp->out_ep->driver_data = NULL;
558	if (fp->in_ep)
559		fp->in_ep->driver_data = NULL;
560	ERROR(cdev, "USB CDC Phonet: cannot autoconfigure\n");
561	return status;
562}
563
564static void
565pn_unbind(struct usb_configuration *c, struct usb_function *f)
566{
567	struct f_phonet *fp = func_to_pn(f);
568	int i;
569
570	/* We are already disconnected */
571	if (fp->in_req)
572		usb_ep_free_request(fp->in_ep, fp->in_req);
573	for (i = 0; i < phonet_rxq_size; i++)
574		if (fp->out_reqv[i])
575			usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
576
577	kfree(fp);
578}
579
580/*-------------------------------------------------------------------------*/
581
582static struct net_device *dev;
583
584int __init phonet_bind_config(struct usb_configuration *c)
585{
586	struct f_phonet *fp;
587	int err, size;
588
589	size = sizeof(*fp) + (phonet_rxq_size * sizeof(struct usb_request *));
590	fp = kzalloc(size, GFP_KERNEL);
591	if (!fp)
592		return -ENOMEM;
593
594	fp->dev = dev;
595	fp->function.name = "phonet";
596	fp->function.bind = pn_bind;
597	fp->function.unbind = pn_unbind;
598	fp->function.set_alt = pn_set_alt;
599	fp->function.get_alt = pn_get_alt;
600	fp->function.disable = pn_disconnect;
601	spin_lock_init(&fp->rx.lock);
602
603	err = usb_add_function(c, &fp->function);
604	if (err)
605		kfree(fp);
606	return err;
607}
608
609int __init gphonet_setup(struct usb_gadget *gadget)
610{
611	struct phonet_port *port;
612	int err;
613
614	/* Create net device */
615	BUG_ON(dev);
616	dev = alloc_netdev(sizeof(*port), "upnlink%d", pn_net_setup);
617	if (!dev)
618		return -ENOMEM;
619
620	port = netdev_priv(dev);
621	spin_lock_init(&port->lock);
622	netif_carrier_off(dev);
623	SET_NETDEV_DEV(dev, &gadget->dev);
624
625	err = register_netdev(dev);
626	if (err)
627		free_netdev(dev);
628	return err;
629}
630
631void gphonet_cleanup(void)
632{
633	unregister_netdev(dev);
634}
635