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 v3.10 814 lines 23 kB view raw
1/***************************************************************************** 2* 3* Filename: ksdazzle.c 4* Version: 0.1.2 5* Description: Irda KingSun Dazzle USB Dongle 6* Status: Experimental 7* Author: Alex Villacís Lasso <a_villacis@palosanto.com> 8* 9* Based on stir4200, mcs7780, kingsun-sir drivers. 10* 11* This program is free software; you can redistribute it and/or modify 12* it under the terms of the GNU General Public License as published by 13* the Free Software Foundation; either version 2 of the License. 14* 15* This program is distributed in the hope that it will be useful, 16* but WITHOUT ANY WARRANTY; without even the implied warranty of 17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18* GNU General Public License for more details. 19* 20* You should have received a copy of the GNU General Public License 21* along with this program; if not, write to the Free Software 22* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23* 24*****************************************************************************/ 25 26/* 27 * Following is my most current (2007-07-26) understanding of how the Kingsun 28 * 07D0:4100 dongle (sometimes known as the MA-660) is supposed to work. This 29 * information was deduced by examining the USB traffic captured with USBSnoopy 30 * from the WinXP driver. Feel free to update here as more of the dongle is 31 * known. 32 * 33 * General: This dongle exposes one interface with two interrupt endpoints, one 34 * IN and one OUT. In this regard, it is similar to what the Kingsun/Donshine 35 * dongle (07c0:4200) exposes. Traffic is raw and needs to be wrapped and 36 * unwrapped manually as in stir4200, kingsun-sir, and ks959-sir. 37 * 38 * Transmission: To transmit an IrDA frame, it is necessary to wrap it, then 39 * split it into multiple segments of up to 7 bytes each, and transmit each in 40 * sequence. It seems that sending a single big block (like kingsun-sir does) 41 * won't work with this dongle. Each segment needs to be prefixed with a value 42 * equal to (unsigned char)0xF8 + <number of bytes in segment>, inside a payload 43 * of exactly 8 bytes. For example, a segment of 1 byte gets prefixed by 0xF9, 44 * and one of 7 bytes gets prefixed by 0xFF. The bytes at the end of the 45 * payload, not considered by the prefix, are ignored (set to 0 by this 46 * implementation). 47 * 48 * Reception: To receive data, the driver must poll the dongle regularly (like 49 * kingsun-sir.c) with interrupt URBs. If data is available, it will be returned 50 * in payloads from 0 to 8 bytes long. When concatenated, these payloads form 51 * a raw IrDA stream that needs to be unwrapped as in stir4200 and kingsun-sir 52 * 53 * Speed change: To change the speed of the dongle, the driver prepares a 54 * control URB with the following as a setup packet: 55 * bRequestType USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE 56 * bRequest 0x09 57 * wValue 0x0200 58 * wIndex 0x0001 59 * wLength 0x0008 (length of the payload) 60 * The payload is a 8-byte record, apparently identical to the one used in 61 * drivers/usb/serial/cypress_m8.c to change speed: 62 * __u32 baudSpeed; 63 * unsigned int dataBits : 2; // 0 - 5 bits 3 - 8 bits 64 * unsigned int : 1; 65 * unsigned int stopBits : 1; 66 * unsigned int parityEnable : 1; 67 * unsigned int parityType : 1; 68 * unsigned int : 1; 69 * unsigned int reset : 1; 70 * unsigned char reserved[3]; // set to 0 71 * 72 * For now only SIR speeds have been observed with this dongle. Therefore, 73 * nothing is known on what changes (if any) must be done to frame wrapping / 74 * unwrapping for higher than SIR speeds. This driver assumes no change is 75 * necessary and announces support for all the way to 115200 bps. 76 */ 77 78#include <linux/module.h> 79#include <linux/moduleparam.h> 80#include <linux/kernel.h> 81#include <linux/types.h> 82#include <linux/errno.h> 83#include <linux/init.h> 84#include <linux/slab.h> 85#include <linux/usb.h> 86#include <linux/device.h> 87#include <linux/crc32.h> 88 89#include <asm/unaligned.h> 90#include <asm/byteorder.h> 91#include <asm/uaccess.h> 92 93#include <net/irda/irda.h> 94#include <net/irda/wrapper.h> 95#include <net/irda/crc.h> 96 97#define KSDAZZLE_VENDOR_ID 0x07d0 98#define KSDAZZLE_PRODUCT_ID 0x4100 99 100/* These are the currently known USB ids */ 101static struct usb_device_id dongles[] = { 102 /* KingSun Co,Ltd IrDA/USB Bridge */ 103 {USB_DEVICE(KSDAZZLE_VENDOR_ID, KSDAZZLE_PRODUCT_ID)}, 104 {} 105}; 106 107MODULE_DEVICE_TABLE(usb, dongles); 108 109#define KINGSUN_MTT 0x07 110#define KINGSUN_REQ_RECV 0x01 111#define KINGSUN_REQ_SEND 0x09 112 113#define KINGSUN_SND_FIFO_SIZE 2048 /* Max packet we can send */ 114#define KINGSUN_RCV_MAX 2048 /* Max transfer we can receive */ 115 116struct ksdazzle_speedparams { 117 __le32 baudrate; /* baud rate, little endian */ 118 __u8 flags; 119 __u8 reserved[3]; 120} __packed; 121 122#define KS_DATA_5_BITS 0x00 123#define KS_DATA_6_BITS 0x01 124#define KS_DATA_7_BITS 0x02 125#define KS_DATA_8_BITS 0x03 126 127#define KS_STOP_BITS_1 0x00 128#define KS_STOP_BITS_2 0x08 129 130#define KS_PAR_DISABLE 0x00 131#define KS_PAR_EVEN 0x10 132#define KS_PAR_ODD 0x30 133#define KS_RESET 0x80 134 135#define KINGSUN_EP_IN 0 136#define KINGSUN_EP_OUT 1 137 138struct ksdazzle_cb { 139 struct usb_device *usbdev; /* init: probe_irda */ 140 struct net_device *netdev; /* network layer */ 141 struct irlap_cb *irlap; /* The link layer we are binded to */ 142 143 struct qos_info qos; 144 145 struct urb *tx_urb; 146 __u8 *tx_buf_clear; 147 unsigned int tx_buf_clear_used; 148 unsigned int tx_buf_clear_sent; 149 __u8 tx_payload[8]; 150 151 struct urb *rx_urb; 152 __u8 *rx_buf; 153 iobuff_t rx_unwrap_buff; 154 155 struct usb_ctrlrequest *speed_setuprequest; 156 struct urb *speed_urb; 157 struct ksdazzle_speedparams speedparams; 158 unsigned int new_speed; 159 160 __u8 ep_in; 161 __u8 ep_out; 162 163 spinlock_t lock; 164 int receiving; 165}; 166 167/* Callback transmission routine */ 168static void ksdazzle_speed_irq(struct urb *urb) 169{ 170 /* unlink, shutdown, unplug, other nasties */ 171 if (urb->status != 0) 172 dev_err(&urb->dev->dev, 173 "ksdazzle_speed_irq: urb asynchronously failed - %d\n", 174 urb->status); 175} 176 177/* Send a control request to change speed of the dongle */ 178static int ksdazzle_change_speed(struct ksdazzle_cb *kingsun, unsigned speed) 179{ 180 static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400, 181 57600, 115200, 576000, 1152000, 4000000, 0 182 }; 183 int err; 184 unsigned int i; 185 186 if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL) 187 return -ENOMEM; 188 189 /* Check that requested speed is among the supported ones */ 190 for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ; 191 if (supported_speeds[i] == 0) 192 return -EOPNOTSUPP; 193 194 memset(&(kingsun->speedparams), 0, sizeof(struct ksdazzle_speedparams)); 195 kingsun->speedparams.baudrate = cpu_to_le32(speed); 196 kingsun->speedparams.flags = KS_DATA_8_BITS; 197 198 /* speed_setuprequest pre-filled in ksdazzle_probe */ 199 usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev, 200 usb_sndctrlpipe(kingsun->usbdev, 0), 201 (unsigned char *)kingsun->speed_setuprequest, 202 &(kingsun->speedparams), 203 sizeof(struct ksdazzle_speedparams), 204 ksdazzle_speed_irq, kingsun); 205 kingsun->speed_urb->status = 0; 206 err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC); 207 208 return err; 209} 210 211/* Submit one fragment of an IrDA frame to the dongle */ 212static void ksdazzle_send_irq(struct urb *urb); 213static int ksdazzle_submit_tx_fragment(struct ksdazzle_cb *kingsun) 214{ 215 unsigned int wraplen; 216 int ret; 217 218 /* We can send at most 7 bytes of payload at a time */ 219 wraplen = 7; 220 if (wraplen > kingsun->tx_buf_clear_used) 221 wraplen = kingsun->tx_buf_clear_used; 222 223 /* Prepare payload prefix with used length */ 224 memset(kingsun->tx_payload, 0, 8); 225 kingsun->tx_payload[0] = (unsigned char)0xf8 + wraplen; 226 memcpy(kingsun->tx_payload + 1, kingsun->tx_buf_clear, wraplen); 227 228 usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev, 229 usb_sndintpipe(kingsun->usbdev, kingsun->ep_out), 230 kingsun->tx_payload, 8, ksdazzle_send_irq, kingsun, 1); 231 kingsun->tx_urb->status = 0; 232 ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC); 233 234 /* Remember how much data was sent, in order to update at callback */ 235 kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0; 236 return ret; 237} 238 239/* Callback transmission routine */ 240static void ksdazzle_send_irq(struct urb *urb) 241{ 242 struct ksdazzle_cb *kingsun = urb->context; 243 struct net_device *netdev = kingsun->netdev; 244 int ret = 0; 245 246 /* in process of stopping, just drop data */ 247 if (!netif_running(kingsun->netdev)) { 248 dev_err(&kingsun->usbdev->dev, 249 "ksdazzle_send_irq: Network not running!\n"); 250 return; 251 } 252 253 /* unlink, shutdown, unplug, other nasties */ 254 if (urb->status != 0) { 255 dev_err(&kingsun->usbdev->dev, 256 "ksdazzle_send_irq: urb asynchronously failed - %d\n", 257 urb->status); 258 return; 259 } 260 261 if (kingsun->tx_buf_clear_used > 0) { 262 /* Update data remaining to be sent */ 263 if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) { 264 memmove(kingsun->tx_buf_clear, 265 kingsun->tx_buf_clear + 266 kingsun->tx_buf_clear_sent, 267 kingsun->tx_buf_clear_used - 268 kingsun->tx_buf_clear_sent); 269 } 270 kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent; 271 kingsun->tx_buf_clear_sent = 0; 272 273 if (kingsun->tx_buf_clear_used > 0) { 274 /* There is more data to be sent */ 275 if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { 276 dev_err(&kingsun->usbdev->dev, 277 "ksdazzle_send_irq: failed tx_urb submit: %d\n", 278 ret); 279 switch (ret) { 280 case -ENODEV: 281 case -EPIPE: 282 break; 283 default: 284 netdev->stats.tx_errors++; 285 netif_start_queue(netdev); 286 } 287 } 288 } else { 289 /* All data sent, send next speed && wake network queue */ 290 if (kingsun->new_speed != -1 && 291 cpu_to_le32(kingsun->new_speed) != 292 kingsun->speedparams.baudrate) 293 ksdazzle_change_speed(kingsun, 294 kingsun->new_speed); 295 296 netif_wake_queue(netdev); 297 } 298 } 299} 300 301/* 302 * Called from net/core when new frame is available. 303 */ 304static netdev_tx_t ksdazzle_hard_xmit(struct sk_buff *skb, 305 struct net_device *netdev) 306{ 307 struct ksdazzle_cb *kingsun; 308 unsigned int wraplen; 309 int ret = 0; 310 311 netif_stop_queue(netdev); 312 313 /* the IRDA wrapping routines don't deal with non linear skb */ 314 SKB_LINEAR_ASSERT(skb); 315 316 kingsun = netdev_priv(netdev); 317 318 spin_lock(&kingsun->lock); 319 kingsun->new_speed = irda_get_next_speed(skb); 320 321 /* Append data to the end of whatever data remains to be transmitted */ 322 wraplen = 323 async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE); 324 kingsun->tx_buf_clear_used = wraplen; 325 326 if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { 327 dev_err(&kingsun->usbdev->dev, 328 "ksdazzle_hard_xmit: failed tx_urb submit: %d\n", ret); 329 switch (ret) { 330 case -ENODEV: 331 case -EPIPE: 332 break; 333 default: 334 netdev->stats.tx_errors++; 335 netif_start_queue(netdev); 336 } 337 } else { 338 netdev->stats.tx_packets++; 339 netdev->stats.tx_bytes += skb->len; 340 341 } 342 343 dev_kfree_skb(skb); 344 spin_unlock(&kingsun->lock); 345 346 return NETDEV_TX_OK; 347} 348 349/* Receive callback function */ 350static void ksdazzle_rcv_irq(struct urb *urb) 351{ 352 struct ksdazzle_cb *kingsun = urb->context; 353 struct net_device *netdev = kingsun->netdev; 354 355 /* in process of stopping, just drop data */ 356 if (!netif_running(netdev)) { 357 kingsun->receiving = 0; 358 return; 359 } 360 361 /* unlink, shutdown, unplug, other nasties */ 362 if (urb->status != 0) { 363 dev_err(&kingsun->usbdev->dev, 364 "ksdazzle_rcv_irq: urb asynchronously failed - %d\n", 365 urb->status); 366 kingsun->receiving = 0; 367 return; 368 } 369 370 if (urb->actual_length > 0) { 371 __u8 *bytes = urb->transfer_buffer; 372 unsigned int i; 373 374 for (i = 0; i < urb->actual_length; i++) { 375 async_unwrap_char(netdev, &netdev->stats, 376 &kingsun->rx_unwrap_buff, bytes[i]); 377 } 378 kingsun->receiving = 379 (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0; 380 } 381 382 /* This urb has already been filled in ksdazzle_net_open. It is assumed that 383 urb keeps the pointer to the payload buffer. 384 */ 385 urb->status = 0; 386 usb_submit_urb(urb, GFP_ATOMIC); 387} 388 389/* 390 * Function ksdazzle_net_open (dev) 391 * 392 * Network device is taken up. Usually this is done by "ifconfig irda0 up" 393 */ 394static int ksdazzle_net_open(struct net_device *netdev) 395{ 396 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 397 int err = -ENOMEM; 398 char hwname[16]; 399 400 /* At this point, urbs are NULL, and skb is NULL (see ksdazzle_probe) */ 401 kingsun->receiving = 0; 402 403 /* Initialize for SIR to copy data directly into skb. */ 404 kingsun->rx_unwrap_buff.in_frame = FALSE; 405 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 406 kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU; 407 kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); 408 if (!kingsun->rx_unwrap_buff.skb) 409 goto free_mem; 410 411 skb_reserve(kingsun->rx_unwrap_buff.skb, 1); 412 kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data; 413 414 kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); 415 if (!kingsun->rx_urb) 416 goto free_mem; 417 418 kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); 419 if (!kingsun->tx_urb) 420 goto free_mem; 421 422 kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL); 423 if (!kingsun->speed_urb) 424 goto free_mem; 425 426 /* Initialize speed for dongle */ 427 kingsun->new_speed = 9600; 428 err = ksdazzle_change_speed(kingsun, 9600); 429 if (err < 0) 430 goto free_mem; 431 432 /* 433 * Now that everything should be initialized properly, 434 * Open new IrLAP layer instance to take care of us... 435 */ 436 sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); 437 kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); 438 if (!kingsun->irlap) { 439 err = -ENOMEM; 440 dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); 441 goto free_mem; 442 } 443 444 /* Start reception. */ 445 usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev, 446 usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in), 447 kingsun->rx_buf, KINGSUN_RCV_MAX, ksdazzle_rcv_irq, 448 kingsun, 1); 449 kingsun->rx_urb->status = 0; 450 err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 451 if (err) { 452 dev_err(&kingsun->usbdev->dev, "first urb-submit failed: %d\n", err); 453 goto close_irlap; 454 } 455 456 netif_start_queue(netdev); 457 458 /* Situation at this point: 459 - all work buffers allocated 460 - urbs allocated and ready to fill 461 - max rx packet known (in max_rx) 462 - unwrap state machine initialized, in state outside of any frame 463 - receive request in progress 464 - IrLAP layer started, about to hand over packets to send 465 */ 466 467 return 0; 468 469 close_irlap: 470 irlap_close(kingsun->irlap); 471 free_mem: 472 usb_free_urb(kingsun->speed_urb); 473 kingsun->speed_urb = NULL; 474 usb_free_urb(kingsun->tx_urb); 475 kingsun->tx_urb = NULL; 476 usb_free_urb(kingsun->rx_urb); 477 kingsun->rx_urb = NULL; 478 if (kingsun->rx_unwrap_buff.skb) { 479 kfree_skb(kingsun->rx_unwrap_buff.skb); 480 kingsun->rx_unwrap_buff.skb = NULL; 481 kingsun->rx_unwrap_buff.head = NULL; 482 } 483 return err; 484} 485 486/* 487 * Function ksdazzle_net_close (dev) 488 * 489 * Network device is taken down. Usually this is done by 490 * "ifconfig irda0 down" 491 */ 492static int ksdazzle_net_close(struct net_device *netdev) 493{ 494 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 495 496 /* Stop transmit processing */ 497 netif_stop_queue(netdev); 498 499 /* Mop up receive && transmit urb's */ 500 usb_kill_urb(kingsun->tx_urb); 501 usb_free_urb(kingsun->tx_urb); 502 kingsun->tx_urb = NULL; 503 504 usb_kill_urb(kingsun->speed_urb); 505 usb_free_urb(kingsun->speed_urb); 506 kingsun->speed_urb = NULL; 507 508 usb_kill_urb(kingsun->rx_urb); 509 usb_free_urb(kingsun->rx_urb); 510 kingsun->rx_urb = NULL; 511 512 kfree_skb(kingsun->rx_unwrap_buff.skb); 513 kingsun->rx_unwrap_buff.skb = NULL; 514 kingsun->rx_unwrap_buff.head = NULL; 515 kingsun->rx_unwrap_buff.in_frame = FALSE; 516 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 517 kingsun->receiving = 0; 518 519 /* Stop and remove instance of IrLAP */ 520 irlap_close(kingsun->irlap); 521 522 kingsun->irlap = NULL; 523 524 return 0; 525} 526 527/* 528 * IOCTLs : Extra out-of-band network commands... 529 */ 530static int ksdazzle_net_ioctl(struct net_device *netdev, struct ifreq *rq, 531 int cmd) 532{ 533 struct if_irda_req *irq = (struct if_irda_req *)rq; 534 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 535 int ret = 0; 536 537 switch (cmd) { 538 case SIOCSBANDWIDTH: /* Set bandwidth */ 539 if (!capable(CAP_NET_ADMIN)) 540 return -EPERM; 541 542 /* Check if the device is still there */ 543 if (netif_device_present(kingsun->netdev)) 544 return ksdazzle_change_speed(kingsun, 545 irq->ifr_baudrate); 546 break; 547 548 case SIOCSMEDIABUSY: /* Set media busy */ 549 if (!capable(CAP_NET_ADMIN)) 550 return -EPERM; 551 552 /* Check if the IrDA stack is still there */ 553 if (netif_running(kingsun->netdev)) 554 irda_device_set_media_busy(kingsun->netdev, TRUE); 555 break; 556 557 case SIOCGRECEIVING: 558 /* Only approximately true */ 559 irq->ifr_receiving = kingsun->receiving; 560 break; 561 562 default: 563 ret = -EOPNOTSUPP; 564 } 565 566 return ret; 567} 568 569static const struct net_device_ops ksdazzle_ops = { 570 .ndo_start_xmit = ksdazzle_hard_xmit, 571 .ndo_open = ksdazzle_net_open, 572 .ndo_stop = ksdazzle_net_close, 573 .ndo_do_ioctl = ksdazzle_net_ioctl, 574}; 575 576/* 577 * This routine is called by the USB subsystem for each new device 578 * in the system. We need to check if the device is ours, and in 579 * this case start handling it. 580 */ 581static int ksdazzle_probe(struct usb_interface *intf, 582 const struct usb_device_id *id) 583{ 584 struct usb_host_interface *interface; 585 struct usb_endpoint_descriptor *endpoint; 586 587 struct usb_device *dev = interface_to_usbdev(intf); 588 struct ksdazzle_cb *kingsun = NULL; 589 struct net_device *net = NULL; 590 int ret = -ENOMEM; 591 int pipe, maxp_in, maxp_out; 592 __u8 ep_in; 593 __u8 ep_out; 594 595 /* Check that there really are two interrupt endpoints. Check based on the 596 one in drivers/usb/input/usbmouse.c 597 */ 598 interface = intf->cur_altsetting; 599 if (interface->desc.bNumEndpoints != 2) { 600 dev_err(&intf->dev, "ksdazzle: expected 2 endpoints, found %d\n", 601 interface->desc.bNumEndpoints); 602 return -ENODEV; 603 } 604 endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; 605 if (!usb_endpoint_is_int_in(endpoint)) { 606 dev_err(&intf->dev, 607 "ksdazzle: endpoint 0 is not interrupt IN\n"); 608 return -ENODEV; 609 } 610 611 ep_in = endpoint->bEndpointAddress; 612 pipe = usb_rcvintpipe(dev, ep_in); 613 maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 614 if (maxp_in > 255 || maxp_in <= 1) { 615 dev_err(&intf->dev, 616 "ksdazzle: endpoint 0 has max packet size %d not in range [2..255]\n", 617 maxp_in); 618 return -ENODEV; 619 } 620 621 endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; 622 if (!usb_endpoint_is_int_out(endpoint)) { 623 dev_err(&intf->dev, 624 "ksdazzle: endpoint 1 is not interrupt OUT\n"); 625 return -ENODEV; 626 } 627 628 ep_out = endpoint->bEndpointAddress; 629 pipe = usb_sndintpipe(dev, ep_out); 630 maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 631 632 /* Allocate network device container. */ 633 net = alloc_irdadev(sizeof(*kingsun)); 634 if (!net) 635 goto err_out1; 636 637 SET_NETDEV_DEV(net, &intf->dev); 638 kingsun = netdev_priv(net); 639 kingsun->netdev = net; 640 kingsun->usbdev = dev; 641 kingsun->ep_in = ep_in; 642 kingsun->ep_out = ep_out; 643 kingsun->irlap = NULL; 644 kingsun->tx_urb = NULL; 645 kingsun->tx_buf_clear = NULL; 646 kingsun->tx_buf_clear_used = 0; 647 kingsun->tx_buf_clear_sent = 0; 648 649 kingsun->rx_urb = NULL; 650 kingsun->rx_buf = NULL; 651 kingsun->rx_unwrap_buff.in_frame = FALSE; 652 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 653 kingsun->rx_unwrap_buff.skb = NULL; 654 kingsun->receiving = 0; 655 spin_lock_init(&kingsun->lock); 656 657 kingsun->speed_setuprequest = NULL; 658 kingsun->speed_urb = NULL; 659 kingsun->speedparams.baudrate = 0; 660 661 /* Allocate input buffer */ 662 kingsun->rx_buf = kmalloc(KINGSUN_RCV_MAX, GFP_KERNEL); 663 if (!kingsun->rx_buf) 664 goto free_mem; 665 666 /* Allocate output buffer */ 667 kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL); 668 if (!kingsun->tx_buf_clear) 669 goto free_mem; 670 671 /* Allocate and initialize speed setup packet */ 672 kingsun->speed_setuprequest = 673 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); 674 if (!kingsun->speed_setuprequest) 675 goto free_mem; 676 kingsun->speed_setuprequest->bRequestType = 677 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; 678 kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND; 679 kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200); 680 kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001); 681 kingsun->speed_setuprequest->wLength = 682 cpu_to_le16(sizeof(struct ksdazzle_speedparams)); 683 684 printk(KERN_INFO "KingSun/Dazzle IRDA/USB found at address %d, " 685 "Vendor: %x, Product: %x\n", 686 dev->devnum, le16_to_cpu(dev->descriptor.idVendor), 687 le16_to_cpu(dev->descriptor.idProduct)); 688 689 /* Initialize QoS for this device */ 690 irda_init_max_qos_capabilies(&kingsun->qos); 691 692 /* Baud rates known to be supported. Please uncomment if devices (other 693 than a SonyEriccson K300 phone) can be shown to support higher speeds 694 with this dongle. 695 */ 696 kingsun->qos.baud_rate.bits = 697 IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200; 698 kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; 699 irda_qos_bits_to_value(&kingsun->qos); 700 701 /* Override the network functions we need to use */ 702 net->netdev_ops = &ksdazzle_ops; 703 704 ret = register_netdev(net); 705 if (ret != 0) 706 goto free_mem; 707 708 dev_info(&net->dev, "IrDA: Registered KingSun/Dazzle device %s\n", 709 net->name); 710 711 usb_set_intfdata(intf, kingsun); 712 713 /* Situation at this point: 714 - all work buffers allocated 715 - setup requests pre-filled 716 - urbs not allocated, set to NULL 717 - max rx packet known (is KINGSUN_FIFO_SIZE) 718 - unwrap state machine (partially) initialized, but skb == NULL 719 */ 720 721 return 0; 722 723 free_mem: 724 kfree(kingsun->speed_setuprequest); 725 kfree(kingsun->tx_buf_clear); 726 kfree(kingsun->rx_buf); 727 free_netdev(net); 728 err_out1: 729 return ret; 730} 731 732/* 733 * The current device is removed, the USB layer tell us to shut it down... 734 */ 735static void ksdazzle_disconnect(struct usb_interface *intf) 736{ 737 struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); 738 739 if (!kingsun) 740 return; 741 742 unregister_netdev(kingsun->netdev); 743 744 /* Mop up receive && transmit urb's */ 745 usb_kill_urb(kingsun->speed_urb); 746 usb_free_urb(kingsun->speed_urb); 747 kingsun->speed_urb = NULL; 748 749 usb_kill_urb(kingsun->tx_urb); 750 usb_free_urb(kingsun->tx_urb); 751 kingsun->tx_urb = NULL; 752 753 usb_kill_urb(kingsun->rx_urb); 754 usb_free_urb(kingsun->rx_urb); 755 kingsun->rx_urb = NULL; 756 757 kfree(kingsun->speed_setuprequest); 758 kfree(kingsun->tx_buf_clear); 759 kfree(kingsun->rx_buf); 760 free_netdev(kingsun->netdev); 761 762 usb_set_intfdata(intf, NULL); 763} 764 765#ifdef CONFIG_PM 766/* USB suspend, so power off the transmitter/receiver */ 767static int ksdazzle_suspend(struct usb_interface *intf, pm_message_t message) 768{ 769 struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); 770 771 netif_device_detach(kingsun->netdev); 772 if (kingsun->speed_urb != NULL) 773 usb_kill_urb(kingsun->speed_urb); 774 if (kingsun->tx_urb != NULL) 775 usb_kill_urb(kingsun->tx_urb); 776 if (kingsun->rx_urb != NULL) 777 usb_kill_urb(kingsun->rx_urb); 778 return 0; 779} 780 781/* Coming out of suspend, so reset hardware */ 782static int ksdazzle_resume(struct usb_interface *intf) 783{ 784 struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); 785 786 if (kingsun->rx_urb != NULL) { 787 /* Setup request already filled in ksdazzle_probe */ 788 usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 789 } 790 netif_device_attach(kingsun->netdev); 791 792 return 0; 793} 794#endif 795 796/* 797 * USB device callbacks 798 */ 799static struct usb_driver irda_driver = { 800 .name = "ksdazzle-sir", 801 .probe = ksdazzle_probe, 802 .disconnect = ksdazzle_disconnect, 803 .id_table = dongles, 804#ifdef CONFIG_PM 805 .suspend = ksdazzle_suspend, 806 .resume = ksdazzle_resume, 807#endif 808}; 809 810module_usb_driver(irda_driver); 811 812MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>"); 813MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun Dazzle"); 814MODULE_LICENSE("GPL");