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 err("ksdazzle_speed_irq: urb asynchronously failed - %d", 173 urb->status); 174 } 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 err("ksdazzle_send_irq: Network not running!"); 249 return; 250 } 251 252 /* unlink, shutdown, unplug, other nasties */ 253 if (urb->status != 0) { 254 err("ksdazzle_send_irq: urb asynchronously failed - %d", 255 urb->status); 256 return; 257 } 258 259 if (kingsun->tx_buf_clear_used > 0) { 260 /* Update data remaining to be sent */ 261 if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) { 262 memmove(kingsun->tx_buf_clear, 263 kingsun->tx_buf_clear + 264 kingsun->tx_buf_clear_sent, 265 kingsun->tx_buf_clear_used - 266 kingsun->tx_buf_clear_sent); 267 } 268 kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent; 269 kingsun->tx_buf_clear_sent = 0; 270 271 if (kingsun->tx_buf_clear_used > 0) { 272 /* There is more data to be sent */ 273 if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { 274 err("ksdazzle_send_irq: failed tx_urb submit: %d", ret); 275 switch (ret) { 276 case -ENODEV: 277 case -EPIPE: 278 break; 279 default: 280 netdev->stats.tx_errors++; 281 netif_start_queue(netdev); 282 } 283 } 284 } else { 285 /* All data sent, send next speed && wake network queue */ 286 if (kingsun->new_speed != -1 && 287 cpu_to_le32(kingsun->new_speed) != 288 kingsun->speedparams.baudrate) 289 ksdazzle_change_speed(kingsun, 290 kingsun->new_speed); 291 292 netif_wake_queue(netdev); 293 } 294 } 295} 296 297/* 298 * Called from net/core when new frame is available. 299 */ 300static netdev_tx_t ksdazzle_hard_xmit(struct sk_buff *skb, 301 struct net_device *netdev) 302{ 303 struct ksdazzle_cb *kingsun; 304 unsigned int wraplen; 305 int ret = 0; 306 307 netif_stop_queue(netdev); 308 309 /* the IRDA wrapping routines don't deal with non linear skb */ 310 SKB_LINEAR_ASSERT(skb); 311 312 kingsun = netdev_priv(netdev); 313 314 spin_lock(&kingsun->lock); 315 kingsun->new_speed = irda_get_next_speed(skb); 316 317 /* Append data to the end of whatever data remains to be transmitted */ 318 wraplen = 319 async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE); 320 kingsun->tx_buf_clear_used = wraplen; 321 322 if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { 323 err("ksdazzle_hard_xmit: failed tx_urb submit: %d", ret); 324 switch (ret) { 325 case -ENODEV: 326 case -EPIPE: 327 break; 328 default: 329 netdev->stats.tx_errors++; 330 netif_start_queue(netdev); 331 } 332 } else { 333 netdev->stats.tx_packets++; 334 netdev->stats.tx_bytes += skb->len; 335 336 } 337 338 dev_kfree_skb(skb); 339 spin_unlock(&kingsun->lock); 340 341 return NETDEV_TX_OK; 342} 343 344/* Receive callback function */ 345static void ksdazzle_rcv_irq(struct urb *urb) 346{ 347 struct ksdazzle_cb *kingsun = urb->context; 348 struct net_device *netdev = kingsun->netdev; 349 350 /* in process of stopping, just drop data */ 351 if (!netif_running(netdev)) { 352 kingsun->receiving = 0; 353 return; 354 } 355 356 /* unlink, shutdown, unplug, other nasties */ 357 if (urb->status != 0) { 358 err("ksdazzle_rcv_irq: urb asynchronously failed - %d", 359 urb->status); 360 kingsun->receiving = 0; 361 return; 362 } 363 364 if (urb->actual_length > 0) { 365 __u8 *bytes = urb->transfer_buffer; 366 unsigned int i; 367 368 for (i = 0; i < urb->actual_length; i++) { 369 async_unwrap_char(netdev, &netdev->stats, 370 &kingsun->rx_unwrap_buff, bytes[i]); 371 } 372 kingsun->receiving = 373 (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0; 374 } 375 376 /* This urb has already been filled in ksdazzle_net_open. It is assumed that 377 urb keeps the pointer to the payload buffer. 378 */ 379 urb->status = 0; 380 usb_submit_urb(urb, GFP_ATOMIC); 381} 382 383/* 384 * Function ksdazzle_net_open (dev) 385 * 386 * Network device is taken up. Usually this is done by "ifconfig irda0 up" 387 */ 388static int ksdazzle_net_open(struct net_device *netdev) 389{ 390 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 391 int err = -ENOMEM; 392 char hwname[16]; 393 394 /* At this point, urbs are NULL, and skb is NULL (see ksdazzle_probe) */ 395 kingsun->receiving = 0; 396 397 /* Initialize for SIR to copy data directly into skb. */ 398 kingsun->rx_unwrap_buff.in_frame = FALSE; 399 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 400 kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU; 401 kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); 402 if (!kingsun->rx_unwrap_buff.skb) 403 goto free_mem; 404 405 skb_reserve(kingsun->rx_unwrap_buff.skb, 1); 406 kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data; 407 408 kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); 409 if (!kingsun->rx_urb) 410 goto free_mem; 411 412 kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); 413 if (!kingsun->tx_urb) 414 goto free_mem; 415 416 kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL); 417 if (!kingsun->speed_urb) 418 goto free_mem; 419 420 /* Initialize speed for dongle */ 421 kingsun->new_speed = 9600; 422 err = ksdazzle_change_speed(kingsun, 9600); 423 if (err < 0) 424 goto free_mem; 425 426 /* 427 * Now that everything should be initialized properly, 428 * Open new IrLAP layer instance to take care of us... 429 */ 430 sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); 431 kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); 432 if (!kingsun->irlap) { 433 err("ksdazzle-sir: irlap_open failed"); 434 goto free_mem; 435 } 436 437 /* Start reception. */ 438 usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev, 439 usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in), 440 kingsun->rx_buf, KINGSUN_RCV_MAX, ksdazzle_rcv_irq, 441 kingsun, 1); 442 kingsun->rx_urb->status = 0; 443 err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 444 if (err) { 445 err("ksdazzle-sir: first urb-submit failed: %d", err); 446 goto close_irlap; 447 } 448 449 netif_start_queue(netdev); 450 451 /* Situation at this point: 452 - all work buffers allocated 453 - urbs allocated and ready to fill 454 - max rx packet known (in max_rx) 455 - unwrap state machine initialized, in state outside of any frame 456 - receive request in progress 457 - IrLAP layer started, about to hand over packets to send 458 */ 459 460 return 0; 461 462 close_irlap: 463 irlap_close(kingsun->irlap); 464 free_mem: 465 usb_free_urb(kingsun->speed_urb); 466 kingsun->speed_urb = NULL; 467 usb_free_urb(kingsun->tx_urb); 468 kingsun->tx_urb = NULL; 469 usb_free_urb(kingsun->rx_urb); 470 kingsun->rx_urb = NULL; 471 if (kingsun->rx_unwrap_buff.skb) { 472 kfree_skb(kingsun->rx_unwrap_buff.skb); 473 kingsun->rx_unwrap_buff.skb = NULL; 474 kingsun->rx_unwrap_buff.head = NULL; 475 } 476 return err; 477} 478 479/* 480 * Function ksdazzle_net_close (dev) 481 * 482 * Network device is taken down. Usually this is done by 483 * "ifconfig irda0 down" 484 */ 485static int ksdazzle_net_close(struct net_device *netdev) 486{ 487 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 488 489 /* Stop transmit processing */ 490 netif_stop_queue(netdev); 491 492 /* Mop up receive && transmit urb's */ 493 usb_kill_urb(kingsun->tx_urb); 494 usb_free_urb(kingsun->tx_urb); 495 kingsun->tx_urb = NULL; 496 497 usb_kill_urb(kingsun->speed_urb); 498 usb_free_urb(kingsun->speed_urb); 499 kingsun->speed_urb = NULL; 500 501 usb_kill_urb(kingsun->rx_urb); 502 usb_free_urb(kingsun->rx_urb); 503 kingsun->rx_urb = NULL; 504 505 kfree_skb(kingsun->rx_unwrap_buff.skb); 506 kingsun->rx_unwrap_buff.skb = NULL; 507 kingsun->rx_unwrap_buff.head = NULL; 508 kingsun->rx_unwrap_buff.in_frame = FALSE; 509 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 510 kingsun->receiving = 0; 511 512 /* Stop and remove instance of IrLAP */ 513 irlap_close(kingsun->irlap); 514 515 kingsun->irlap = NULL; 516 517 return 0; 518} 519 520/* 521 * IOCTLs : Extra out-of-band network commands... 522 */ 523static int ksdazzle_net_ioctl(struct net_device *netdev, struct ifreq *rq, 524 int cmd) 525{ 526 struct if_irda_req *irq = (struct if_irda_req *)rq; 527 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 528 int ret = 0; 529 530 switch (cmd) { 531 case SIOCSBANDWIDTH: /* Set bandwidth */ 532 if (!capable(CAP_NET_ADMIN)) 533 return -EPERM; 534 535 /* Check if the device is still there */ 536 if (netif_device_present(kingsun->netdev)) 537 return ksdazzle_change_speed(kingsun, 538 irq->ifr_baudrate); 539 break; 540 541 case SIOCSMEDIABUSY: /* Set media busy */ 542 if (!capable(CAP_NET_ADMIN)) 543 return -EPERM; 544 545 /* Check if the IrDA stack is still there */ 546 if (netif_running(kingsun->netdev)) 547 irda_device_set_media_busy(kingsun->netdev, TRUE); 548 break; 549 550 case SIOCGRECEIVING: 551 /* Only approximately true */ 552 irq->ifr_receiving = kingsun->receiving; 553 break; 554 555 default: 556 ret = -EOPNOTSUPP; 557 } 558 559 return ret; 560} 561 562static const struct net_device_ops ksdazzle_ops = { 563 .ndo_start_xmit = ksdazzle_hard_xmit, 564 .ndo_open = ksdazzle_net_open, 565 .ndo_stop = ksdazzle_net_close, 566 .ndo_do_ioctl = ksdazzle_net_ioctl, 567}; 568 569/* 570 * This routine is called by the USB subsystem for each new device 571 * in the system. We need to check if the device is ours, and in 572 * this case start handling it. 573 */ 574static int ksdazzle_probe(struct usb_interface *intf, 575 const struct usb_device_id *id) 576{ 577 struct usb_host_interface *interface; 578 struct usb_endpoint_descriptor *endpoint; 579 580 struct usb_device *dev = interface_to_usbdev(intf); 581 struct ksdazzle_cb *kingsun = NULL; 582 struct net_device *net = NULL; 583 int ret = -ENOMEM; 584 int pipe, maxp_in, maxp_out; 585 __u8 ep_in; 586 __u8 ep_out; 587 588 /* Check that there really are two interrupt endpoints. Check based on the 589 one in drivers/usb/input/usbmouse.c 590 */ 591 interface = intf->cur_altsetting; 592 if (interface->desc.bNumEndpoints != 2) { 593 err("ksdazzle: expected 2 endpoints, found %d", 594 interface->desc.bNumEndpoints); 595 return -ENODEV; 596 } 597 endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; 598 if (!usb_endpoint_is_int_in(endpoint)) { 599 err("ksdazzle: endpoint 0 is not interrupt IN"); 600 return -ENODEV; 601 } 602 603 ep_in = endpoint->bEndpointAddress; 604 pipe = usb_rcvintpipe(dev, ep_in); 605 maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 606 if (maxp_in > 255 || maxp_in <= 1) { 607 err("ksdazzle: endpoint 0 has max packet size %d not in range [2..255]", maxp_in); 608 return -ENODEV; 609 } 610 611 endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; 612 if (!usb_endpoint_is_int_out(endpoint)) { 613 err("ksdazzle: endpoint 1 is not interrupt OUT"); 614 return -ENODEV; 615 } 616 617 ep_out = endpoint->bEndpointAddress; 618 pipe = usb_sndintpipe(dev, ep_out); 619 maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 620 621 /* Allocate network device container. */ 622 net = alloc_irdadev(sizeof(*kingsun)); 623 if (!net) 624 goto err_out1; 625 626 SET_NETDEV_DEV(net, &intf->dev); 627 kingsun = netdev_priv(net); 628 kingsun->netdev = net; 629 kingsun->usbdev = dev; 630 kingsun->ep_in = ep_in; 631 kingsun->ep_out = ep_out; 632 kingsun->irlap = NULL; 633 kingsun->tx_urb = NULL; 634 kingsun->tx_buf_clear = NULL; 635 kingsun->tx_buf_clear_used = 0; 636 kingsun->tx_buf_clear_sent = 0; 637 638 kingsun->rx_urb = NULL; 639 kingsun->rx_buf = NULL; 640 kingsun->rx_unwrap_buff.in_frame = FALSE; 641 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 642 kingsun->rx_unwrap_buff.skb = NULL; 643 kingsun->receiving = 0; 644 spin_lock_init(&kingsun->lock); 645 646 kingsun->speed_setuprequest = NULL; 647 kingsun->speed_urb = NULL; 648 kingsun->speedparams.baudrate = 0; 649 650 /* Allocate input buffer */ 651 kingsun->rx_buf = kmalloc(KINGSUN_RCV_MAX, GFP_KERNEL); 652 if (!kingsun->rx_buf) 653 goto free_mem; 654 655 /* Allocate output buffer */ 656 kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL); 657 if (!kingsun->tx_buf_clear) 658 goto free_mem; 659 660 /* Allocate and initialize speed setup packet */ 661 kingsun->speed_setuprequest = 662 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); 663 if (!kingsun->speed_setuprequest) 664 goto free_mem; 665 kingsun->speed_setuprequest->bRequestType = 666 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; 667 kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND; 668 kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200); 669 kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001); 670 kingsun->speed_setuprequest->wLength = 671 cpu_to_le16(sizeof(struct ksdazzle_speedparams)); 672 673 printk(KERN_INFO "KingSun/Dazzle IRDA/USB found at address %d, " 674 "Vendor: %x, Product: %x\n", 675 dev->devnum, le16_to_cpu(dev->descriptor.idVendor), 676 le16_to_cpu(dev->descriptor.idProduct)); 677 678 /* Initialize QoS for this device */ 679 irda_init_max_qos_capabilies(&kingsun->qos); 680 681 /* Baud rates known to be supported. Please uncomment if devices (other 682 than a SonyEriccson K300 phone) can be shown to support higher speeds 683 with this dongle. 684 */ 685 kingsun->qos.baud_rate.bits = 686 IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200; 687 kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; 688 irda_qos_bits_to_value(&kingsun->qos); 689 690 /* Override the network functions we need to use */ 691 net->netdev_ops = &ksdazzle_ops; 692 693 ret = register_netdev(net); 694 if (ret != 0) 695 goto free_mem; 696 697 dev_info(&net->dev, "IrDA: Registered KingSun/Dazzle device %s\n", 698 net->name); 699 700 usb_set_intfdata(intf, kingsun); 701 702 /* Situation at this point: 703 - all work buffers allocated 704 - setup requests pre-filled 705 - urbs not allocated, set to NULL 706 - max rx packet known (is KINGSUN_FIFO_SIZE) 707 - unwrap state machine (partially) initialized, but skb == NULL 708 */ 709 710 return 0; 711 712 free_mem: 713 kfree(kingsun->speed_setuprequest); 714 kfree(kingsun->tx_buf_clear); 715 kfree(kingsun->rx_buf); 716 free_netdev(net); 717 err_out1: 718 return ret; 719} 720 721/* 722 * The current device is removed, the USB layer tell us to shut it down... 723 */ 724static void ksdazzle_disconnect(struct usb_interface *intf) 725{ 726 struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); 727 728 if (!kingsun) 729 return; 730 731 unregister_netdev(kingsun->netdev); 732 733 /* Mop up receive && transmit urb's */ 734 usb_kill_urb(kingsun->speed_urb); 735 usb_free_urb(kingsun->speed_urb); 736 kingsun->speed_urb = NULL; 737 738 usb_kill_urb(kingsun->tx_urb); 739 usb_free_urb(kingsun->tx_urb); 740 kingsun->tx_urb = NULL; 741 742 usb_kill_urb(kingsun->rx_urb); 743 usb_free_urb(kingsun->rx_urb); 744 kingsun->rx_urb = NULL; 745 746 kfree(kingsun->speed_setuprequest); 747 kfree(kingsun->tx_buf_clear); 748 kfree(kingsun->rx_buf); 749 free_netdev(kingsun->netdev); 750 751 usb_set_intfdata(intf, NULL); 752} 753 754#ifdef CONFIG_PM 755/* USB suspend, so power off the transmitter/receiver */ 756static int ksdazzle_suspend(struct usb_interface *intf, pm_message_t message) 757{ 758 struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); 759 760 netif_device_detach(kingsun->netdev); 761 if (kingsun->speed_urb != NULL) 762 usb_kill_urb(kingsun->speed_urb); 763 if (kingsun->tx_urb != NULL) 764 usb_kill_urb(kingsun->tx_urb); 765 if (kingsun->rx_urb != NULL) 766 usb_kill_urb(kingsun->rx_urb); 767 return 0; 768} 769 770/* Coming out of suspend, so reset hardware */ 771static int ksdazzle_resume(struct usb_interface *intf) 772{ 773 struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); 774 775 if (kingsun->rx_urb != NULL) { 776 /* Setup request already filled in ksdazzle_probe */ 777 usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 778 } 779 netif_device_attach(kingsun->netdev); 780 781 return 0; 782} 783#endif 784 785/* 786 * USB device callbacks 787 */ 788static struct usb_driver irda_driver = { 789 .name = "ksdazzle-sir", 790 .probe = ksdazzle_probe, 791 .disconnect = ksdazzle_disconnect, 792 .id_table = dongles, 793#ifdef CONFIG_PM 794 .suspend = ksdazzle_suspend, 795 .resume = ksdazzle_resume, 796#endif 797}; 798 799module_usb_driver(irda_driver); 800 801MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>"); 802MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun Dazzle"); 803MODULE_LICENSE("GPL"); 804