Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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