linux/drivers/net/irda/ks959-sir.c
<<
>>
Prefs
   1/*****************************************************************************
   2*
   3* Filename:      ks959-sir.c
   4* Version:       0.1.2
   5* Description:   Irda KingSun KS-959 USB Dongle
   6* Status:        Experimental
   7* Author:        Alex Villacís Lasso <a_villacis@palosanto.com>
   8*         with help from Domen Puncer <domen@coderock.org>
   9*
  10*    Based on stir4200, mcs7780, kingsun-sir drivers.
  11*
  12*    This program is free software; you can redistribute it and/or modify
  13*    it under the terms of the GNU General Public License as published by
  14*    the Free Software Foundation; either version 2 of the License.
  15*
  16*    This program is distributed in the hope that it will be useful,
  17*    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19*    GNU General Public License for more details.
  20*
  21*    You should have received a copy of the GNU General Public License
  22*    along with this program; if not, write to the Free Software
  23*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24*
  25*****************************************************************************/
  26
  27/*
  28 * Following is my most current (2007-07-17) understanding of how the Kingsun
  29 * KS-959 dongle is supposed to work. This information was deduced by
  30 * reverse-engineering and examining the USB traffic captured with USBSnoopy
  31 * from the WinXP driver. Feel free to update here as more of the dongle is
  32 * known.
  33 *
  34 * My most sincere thanks must go to Domen Puncer <domen@coderock.org> for
  35 * invaluable help in cracking the obfuscation and padding required for this
  36 * dongle.
  37 *
  38 * General: This dongle exposes one interface with one interrupt IN endpoint.
  39 * However, the interrupt endpoint is NOT used at all for this dongle. Instead,
  40 * this dongle uses control transfers for everything, including sending and
  41 * receiving the IrDA frame data. Apparently the interrupt endpoint is just a
  42 * dummy to ensure the dongle has a valid interface to present to the PC.And I
  43 * thought the DonShine dongle was weird... In addition, this dongle uses
  44 * obfuscation (?!?!), applied at the USB level, to hide the traffic, both sent
  45 * and received, from the dongle. I call it obfuscation because the XOR keying
  46 * and padding required to produce an USB traffic acceptable for the dongle can
  47 * not be explained by any other technical requirement.
  48 *
  49 * Transmission: To transmit an IrDA frame, the driver must prepare a control
  50 * URB with the following as a setup packet:
  51 *    bRequestType    USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
  52 *    bRequest        0x09
  53 *    wValue          <length of valid data before padding, little endian>
  54 *    wIndex          0x0000
  55 *    wLength         <length of padded data>
  56 * The payload packet must be manually wrapped and escaped (as in stir4200.c),
  57 * then padded and obfuscated before being sent. Both padding and obfuscation
  58 * are implemented in the procedure obfuscate_tx_buffer(). Suffice to say, the
  59 * designer/programmer of the dongle used his name as a source for the
  60 * obfuscation. WTF?!
  61 * Apparently the dongle cannot handle payloads larger than 256 bytes. The
  62 * driver has to perform fragmentation in order to send anything larger than
  63 * this limit.
  64 *
  65 * Reception: To receive data, the driver must poll the dongle regularly (like
  66 * kingsun-sir.c) with control URBs and the following as a setup packet:
  67 *    bRequestType    USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE
  68 *    bRequest        0x01
  69 *    wValue          0x0200
  70 *    wIndex          0x0000
  71 *    wLength         0x0800 (size of available buffer)
  72 * If there is data to be read, it will be returned as the response payload.
  73 * This data is (apparently) not padded, but it is obfuscated. To de-obfuscate
  74 * it, the driver must XOR every byte, in sequence, with a value that starts at
  75 * 1 and is incremented with each byte processed, and then with 0x55. The value
  76 * incremented with each byte processed overflows as an unsigned char. The
  77 * resulting bytes form a wrapped SIR frame that is unwrapped and unescaped
  78 * as in stir4200.c The incremented value is NOT reset with each frame, but is
  79 * kept across the entire session with the dongle. Also, the dongle inserts an
  80 * extra garbage byte with value 0x95 (after decoding) every 0xff bytes, which
  81 * must be skipped.
  82 *
  83 * Speed change: To change the speed of the dongle, the driver prepares a
  84 * control URB with the following as a setup packet:
  85 *    bRequestType    USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
  86 *    bRequest        0x09
  87 *    wValue          0x0200
  88 *    wIndex          0x0001
  89 *    wLength         0x0008 (length of the payload)
  90 * The payload is a 8-byte record, apparently identical to the one used in
  91 * drivers/usb/serial/cypress_m8.c to change speed:
  92 *     __u32 baudSpeed;
  93 *    unsigned int dataBits : 2;    // 0 - 5 bits 3 - 8 bits
  94 *    unsigned int : 1;
  95 *    unsigned int stopBits : 1;
  96 *    unsigned int parityEnable : 1;
  97 *    unsigned int parityType : 1;
  98 *    unsigned int : 1;
  99 *    unsigned int reset : 1;
 100 *    unsigned char reserved[3];    // set to 0
 101 *
 102 * For now only SIR speeds have been observed with this dongle. Therefore,
 103 * nothing is known on what changes (if any) must be done to frame wrapping /
 104 * unwrapping for higher than SIR speeds. This driver assumes no change is
 105 * necessary and announces support for all the way to 57600 bps. Although the
 106 * package announces support for up to 4MBps, tests with a Sony Ericcson K300
 107 * phone show corruption when receiving large frames at 115200 bps, the highest
 108 * speed announced by the phone. However, transmission at 115200 bps is OK. Go
 109 * figure. Since I don't know whether the phone or the dongle is at fault, max
 110 * announced speed is 57600 bps until someone produces a device that can run
 111 * at higher speeds with this dongle.
 112 */
 113
 114#include <linux/module.h>
 115#include <linux/moduleparam.h>
 116#include <linux/kernel.h>
 117#include <linux/types.h>
 118#include <linux/errno.h>
 119#include <linux/slab.h>
 120#include <linux/usb.h>
 121#include <linux/device.h>
 122#include <linux/crc32.h>
 123
 124#include <asm/unaligned.h>
 125#include <asm/byteorder.h>
 126#include <asm/uaccess.h>
 127
 128#include <net/irda/irda.h>
 129#include <net/irda/wrapper.h>
 130#include <net/irda/crc.h>
 131
 132#define KS959_VENDOR_ID 0x07d0
 133#define KS959_PRODUCT_ID 0x4959
 134
 135/* These are the currently known USB ids */
 136static struct usb_device_id dongles[] = {
 137        /* KingSun Co,Ltd  IrDA/USB Bridge */
 138        {USB_DEVICE(KS959_VENDOR_ID, KS959_PRODUCT_ID)},
 139        {}
 140};
 141
 142MODULE_DEVICE_TABLE(usb, dongles);
 143
 144#define KINGSUN_MTT 0x07
 145#define KINGSUN_REQ_RECV 0x01
 146#define KINGSUN_REQ_SEND 0x09
 147
 148#define KINGSUN_RCV_FIFO_SIZE    2048   /* Max length we can receive */
 149#define KINGSUN_SND_FIFO_SIZE    2048   /* Max packet we can send */
 150#define KINGSUN_SND_PACKET_SIZE    256  /* Max packet dongle can handle */
 151
 152struct ks959_speedparams {
 153        __le32 baudrate;        /* baud rate, little endian */
 154        __u8 flags;
 155        __u8 reserved[3];
 156} __packed;
 157
 158#define KS_DATA_5_BITS 0x00
 159#define KS_DATA_6_BITS 0x01
 160#define KS_DATA_7_BITS 0x02
 161#define KS_DATA_8_BITS 0x03
 162
 163#define KS_STOP_BITS_1 0x00
 164#define KS_STOP_BITS_2 0x08
 165
 166#define KS_PAR_DISABLE    0x00
 167#define KS_PAR_EVEN    0x10
 168#define KS_PAR_ODD    0x30
 169#define KS_RESET    0x80
 170
 171struct ks959_cb {
 172        struct usb_device *usbdev;      /* init: probe_irda */
 173        struct net_device *netdev;      /* network layer */
 174        struct irlap_cb *irlap; /* The link layer we are binded to */
 175
 176        struct qos_info qos;
 177
 178        struct usb_ctrlrequest *tx_setuprequest;
 179        struct urb *tx_urb;
 180        __u8 *tx_buf_clear;
 181        unsigned int tx_buf_clear_used;
 182        unsigned int tx_buf_clear_sent;
 183        __u8 *tx_buf_xored;
 184
 185        struct usb_ctrlrequest *rx_setuprequest;
 186        struct urb *rx_urb;
 187        __u8 *rx_buf;
 188        __u8 rx_variable_xormask;
 189        iobuff_t rx_unwrap_buff;
 190
 191        struct usb_ctrlrequest *speed_setuprequest;
 192        struct urb *speed_urb;
 193        struct ks959_speedparams speedparams;
 194        unsigned int new_speed;
 195
 196        spinlock_t lock;
 197        int receiving;
 198};
 199
 200/* Procedure to perform the obfuscation/padding expected by the dongle
 201 *
 202 * buf_cleartext    (IN) Cleartext version of the IrDA frame to transmit
 203 * len_cleartext    (IN) Length of the cleartext version of IrDA frame
 204 * buf_xoredtext    (OUT) Obfuscated version of frame built by proc
 205 * len_maxbuf        (OUT) Maximum space available at buf_xoredtext
 206 *
 207 * (return)         length of obfuscated frame with padding
 208 *
 209 * If not enough space (as indicated by len_maxbuf vs. required padding),
 210 * zero is returned
 211 *
 212 * The value of lookup_string is actually a required portion of the algorithm.
 213 * Seems the designer of the dongle wanted to state who exactly is responsible
 214 * for implementing obfuscation. Send your best (or other) wishes to him ]:-)
 215 */
 216static unsigned int obfuscate_tx_buffer(const __u8 * buf_cleartext,
 217                                        unsigned int len_cleartext,
 218                                        __u8 * buf_xoredtext,
 219                                        unsigned int len_maxbuf)
 220{
 221        unsigned int len_xoredtext;
 222
 223        /* Calculate required length with padding, check for necessary space */
 224        len_xoredtext = ((len_cleartext + 7) & ~0x7) + 0x10;
 225        if (len_xoredtext <= len_maxbuf) {
 226                static const __u8 lookup_string[] = "wangshuofei19710";
 227                __u8 xor_mask;
 228
 229                /* Unlike the WinXP driver, we *do* clear out the padding */
 230                memset(buf_xoredtext, 0, len_xoredtext);
 231
 232                xor_mask = lookup_string[(len_cleartext & 0x0f) ^ 0x06] ^ 0x55;
 233
 234                while (len_cleartext-- > 0) {
 235                        *buf_xoredtext++ = *buf_cleartext++ ^ xor_mask;
 236                }
 237        } else {
 238                len_xoredtext = 0;
 239        }
 240        return len_xoredtext;
 241}
 242
 243/* Callback transmission routine */
 244static void ks959_speed_irq(struct urb *urb)
 245{
 246        /* unlink, shutdown, unplug, other nasties */
 247        if (urb->status != 0) {
 248                dev_err(&urb->dev->dev,
 249                        "ks959_speed_irq: urb asynchronously failed - %d\n",
 250                        urb->status);
 251        }
 252}
 253
 254/* Send a control request to change speed of the dongle */
 255static int ks959_change_speed(struct ks959_cb *kingsun, unsigned speed)
 256{
 257        static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400,
 258                57600, 115200, 576000, 1152000, 4000000, 0
 259        };
 260        int err;
 261        unsigned int i;
 262
 263        if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL)
 264                return -ENOMEM;
 265
 266        /* Check that requested speed is among the supported ones */
 267        for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ;
 268        if (supported_speeds[i] == 0)
 269                return -EOPNOTSUPP;
 270
 271        memset(&(kingsun->speedparams), 0, sizeof(struct ks959_speedparams));
 272        kingsun->speedparams.baudrate = cpu_to_le32(speed);
 273        kingsun->speedparams.flags = KS_DATA_8_BITS;
 274
 275        /* speed_setuprequest pre-filled in ks959_probe */
 276        usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev,
 277                             usb_sndctrlpipe(kingsun->usbdev, 0),
 278                             (unsigned char *)kingsun->speed_setuprequest,
 279                             &(kingsun->speedparams),
 280                             sizeof(struct ks959_speedparams), ks959_speed_irq,
 281                             kingsun);
 282        kingsun->speed_urb->status = 0;
 283        err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC);
 284
 285        return err;
 286}
 287
 288/* Submit one fragment of an IrDA frame to the dongle */
 289static void ks959_send_irq(struct urb *urb);
 290static int ks959_submit_tx_fragment(struct ks959_cb *kingsun)
 291{
 292        unsigned int padlen;
 293        unsigned int wraplen;
 294        int ret;
 295
 296        /* Check whether current plaintext can produce a padded buffer that fits
 297           within the range handled by the dongle */
 298        wraplen = (KINGSUN_SND_PACKET_SIZE & ~0x7) - 0x10;
 299        if (wraplen > kingsun->tx_buf_clear_used)
 300                wraplen = kingsun->tx_buf_clear_used;
 301
 302        /* Perform dongle obfuscation. Also remove the portion of the frame that
 303           was just obfuscated and will now be sent to the dongle. */
 304        padlen = obfuscate_tx_buffer(kingsun->tx_buf_clear, wraplen,
 305                                     kingsun->tx_buf_xored,
 306                                     KINGSUN_SND_PACKET_SIZE);
 307
 308        /* Calculate how much data can be transmitted in this urb */
 309        kingsun->tx_setuprequest->wValue = cpu_to_le16(wraplen);
 310        kingsun->tx_setuprequest->wLength = cpu_to_le16(padlen);
 311        /* Rest of the fields were filled in ks959_probe */
 312        usb_fill_control_urb(kingsun->tx_urb, kingsun->usbdev,
 313                             usb_sndctrlpipe(kingsun->usbdev, 0),
 314                             (unsigned char *)kingsun->tx_setuprequest,
 315                             kingsun->tx_buf_xored, padlen,
 316                             ks959_send_irq, kingsun);
 317        kingsun->tx_urb->status = 0;
 318        ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC);
 319
 320        /* Remember how much data was sent, in order to update at callback */
 321        kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0;
 322        return ret;
 323}
 324
 325/* Callback transmission routine */
 326static void ks959_send_irq(struct urb *urb)
 327{
 328        struct ks959_cb *kingsun = urb->context;
 329        struct net_device *netdev = kingsun->netdev;
 330        int ret = 0;
 331
 332        /* in process of stopping, just drop data */
 333        if (!netif_running(kingsun->netdev)) {
 334                dev_err(&kingsun->usbdev->dev,
 335                        "ks959_send_irq: Network not running!\n");
 336                return;
 337        }
 338
 339        /* unlink, shutdown, unplug, other nasties */
 340        if (urb->status != 0) {
 341                dev_err(&kingsun->usbdev->dev,
 342                        "ks959_send_irq: urb asynchronously failed - %d\n",
 343                        urb->status);
 344                return;
 345        }
 346
 347        if (kingsun->tx_buf_clear_used > 0) {
 348                /* Update data remaining to be sent */
 349                if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) {
 350                        memmove(kingsun->tx_buf_clear,
 351                                kingsun->tx_buf_clear +
 352                                kingsun->tx_buf_clear_sent,
 353                                kingsun->tx_buf_clear_used -
 354                                kingsun->tx_buf_clear_sent);
 355                }
 356                kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent;
 357                kingsun->tx_buf_clear_sent = 0;
 358
 359                if (kingsun->tx_buf_clear_used > 0) {
 360                        /* There is more data to be sent */
 361                        if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
 362                                dev_err(&kingsun->usbdev->dev,
 363                                        "ks959_send_irq: failed tx_urb submit: %d\n",
 364                                        ret);
 365                                switch (ret) {
 366                                case -ENODEV:
 367                                case -EPIPE:
 368                                        break;
 369                                default:
 370                                        netdev->stats.tx_errors++;
 371                                        netif_start_queue(netdev);
 372                                }
 373                        }
 374                } else {
 375                        /* All data sent, send next speed && wake network queue */
 376                        if (kingsun->new_speed != -1 &&
 377                            cpu_to_le32(kingsun->new_speed) !=
 378                            kingsun->speedparams.baudrate)
 379                                ks959_change_speed(kingsun, kingsun->new_speed);
 380
 381                        netif_wake_queue(netdev);
 382                }
 383        }
 384}
 385
 386/*
 387 * Called from net/core when new frame is available.
 388 */
 389static netdev_tx_t ks959_hard_xmit(struct sk_buff *skb,
 390                                         struct net_device *netdev)
 391{
 392        struct ks959_cb *kingsun;
 393        unsigned int wraplen;
 394        int ret = 0;
 395
 396        netif_stop_queue(netdev);
 397
 398        /* the IRDA wrapping routines don't deal with non linear skb */
 399        SKB_LINEAR_ASSERT(skb);
 400
 401        kingsun = netdev_priv(netdev);
 402
 403        spin_lock(&kingsun->lock);
 404        kingsun->new_speed = irda_get_next_speed(skb);
 405
 406        /* Append data to the end of whatever data remains to be transmitted */
 407        wraplen =
 408            async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE);
 409        kingsun->tx_buf_clear_used = wraplen;
 410
 411        if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
 412                dev_err(&kingsun->usbdev->dev,
 413                        "ks959_hard_xmit: failed tx_urb submit: %d\n", ret);
 414                switch (ret) {
 415                case -ENODEV:
 416                case -EPIPE:
 417                        break;
 418                default:
 419                        netdev->stats.tx_errors++;
 420                        netif_start_queue(netdev);
 421                }
 422        } else {
 423                netdev->stats.tx_packets++;
 424                netdev->stats.tx_bytes += skb->len;
 425
 426        }
 427
 428        dev_kfree_skb(skb);
 429        spin_unlock(&kingsun->lock);
 430
 431        return NETDEV_TX_OK;
 432}
 433
 434/* Receive callback function */
 435static void ks959_rcv_irq(struct urb *urb)
 436{
 437        struct ks959_cb *kingsun = urb->context;
 438        int ret;
 439
 440        /* in process of stopping, just drop data */
 441        if (!netif_running(kingsun->netdev)) {
 442                kingsun->receiving = 0;
 443                return;
 444        }
 445
 446        /* unlink, shutdown, unplug, other nasties */
 447        if (urb->status != 0) {
 448                dev_err(&kingsun->usbdev->dev,
 449                        "kingsun_rcv_irq: urb asynchronously failed - %d\n",
 450                        urb->status);
 451                kingsun->receiving = 0;
 452                return;
 453        }
 454
 455        if (urb->actual_length > 0) {
 456                __u8 *bytes = urb->transfer_buffer;
 457                unsigned int i;
 458
 459                for (i = 0; i < urb->actual_length; i++) {
 460                        /* De-obfuscation implemented here: variable portion of
 461                           xormask is incremented, and then used with the encoded
 462                           byte for the XOR. The result of the operation is used
 463                           to unwrap the SIR frame. */
 464                        kingsun->rx_variable_xormask++;
 465                        bytes[i] =
 466                            bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u;
 467
 468                        /* rx_variable_xormask doubles as an index counter so we
 469                           can skip the byte at 0xff (wrapped around to 0).
 470                         */
 471                        if (kingsun->rx_variable_xormask != 0) {
 472                                async_unwrap_char(kingsun->netdev,
 473                                                  &kingsun->netdev->stats,
 474                                                  &kingsun->rx_unwrap_buff,
 475                                                  bytes[i]);
 476                        }
 477                }
 478                kingsun->receiving =
 479                    (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
 480        }
 481
 482        /* This urb has already been filled in kingsun_net_open. Setup
 483           packet must be re-filled, but it is assumed that urb keeps the
 484           pointer to the initial setup packet, as well as the payload buffer.
 485           Setup packet is already pre-filled at ks959_probe.
 486         */
 487        urb->status = 0;
 488        ret = usb_submit_urb(urb, GFP_ATOMIC);
 489}
 490
 491/*
 492 * Function kingsun_net_open (dev)
 493 *
 494 *    Network device is taken up. Usually this is done by "ifconfig irda0 up"
 495 */
 496static int ks959_net_open(struct net_device *netdev)
 497{
 498        struct ks959_cb *kingsun = netdev_priv(netdev);
 499        int err = -ENOMEM;
 500        char hwname[16];
 501
 502        /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
 503        kingsun->receiving = 0;
 504
 505        /* Initialize for SIR to copy data directly into skb.  */
 506        kingsun->rx_unwrap_buff.in_frame = FALSE;
 507        kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
 508        kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU;
 509        kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
 510        if (!kingsun->rx_unwrap_buff.skb)
 511                goto free_mem;
 512
 513        skb_reserve(kingsun->rx_unwrap_buff.skb, 1);
 514        kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data;
 515
 516        kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
 517        if (!kingsun->rx_urb)
 518                goto free_mem;
 519
 520        kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
 521        if (!kingsun->tx_urb)
 522                goto free_mem;
 523
 524        kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL);
 525        if (!kingsun->speed_urb)
 526                goto free_mem;
 527
 528        /* Initialize speed for dongle */
 529        kingsun->new_speed = 9600;
 530        err = ks959_change_speed(kingsun, 9600);
 531        if (err < 0)
 532                goto free_mem;
 533
 534        /*
 535         * Now that everything should be initialized properly,
 536         * Open new IrLAP layer instance to take care of us...
 537         */
 538        sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
 539        kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
 540        if (!kingsun->irlap) {
 541                err = -ENOMEM;
 542                dev_err(&kingsun->usbdev->dev, "irlap_open failed\n");
 543                goto free_mem;
 544        }
 545
 546        /* Start reception. Setup request already pre-filled in ks959_probe */
 547        usb_fill_control_urb(kingsun->rx_urb, kingsun->usbdev,
 548                             usb_rcvctrlpipe(kingsun->usbdev, 0),
 549                             (unsigned char *)kingsun->rx_setuprequest,
 550                             kingsun->rx_buf, KINGSUN_RCV_FIFO_SIZE,
 551                             ks959_rcv_irq, kingsun);
 552        kingsun->rx_urb->status = 0;
 553        err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
 554        if (err) {
 555                dev_err(&kingsun->usbdev->dev,
 556                        "first urb-submit failed: %d\n", err);
 557                goto close_irlap;
 558        }
 559
 560        netif_start_queue(netdev);
 561
 562        /* Situation at this point:
 563           - all work buffers allocated
 564           - urbs allocated and ready to fill
 565           - max rx packet known (in max_rx)
 566           - unwrap state machine initialized, in state outside of any frame
 567           - receive request in progress
 568           - IrLAP layer started, about to hand over packets to send
 569         */
 570
 571        return 0;
 572
 573      close_irlap:
 574        irlap_close(kingsun->irlap);
 575      free_mem:
 576        usb_free_urb(kingsun->speed_urb);
 577        kingsun->speed_urb = NULL;
 578        usb_free_urb(kingsun->tx_urb);
 579        kingsun->tx_urb = NULL;
 580        usb_free_urb(kingsun->rx_urb);
 581        kingsun->rx_urb = NULL;
 582        if (kingsun->rx_unwrap_buff.skb) {
 583                kfree_skb(kingsun->rx_unwrap_buff.skb);
 584                kingsun->rx_unwrap_buff.skb = NULL;
 585                kingsun->rx_unwrap_buff.head = NULL;
 586        }
 587        return err;
 588}
 589
 590/*
 591 * Function kingsun_net_close (kingsun)
 592 *
 593 *    Network device is taken down. Usually this is done by
 594 *    "ifconfig irda0 down"
 595 */
 596static int ks959_net_close(struct net_device *netdev)
 597{
 598        struct ks959_cb *kingsun = netdev_priv(netdev);
 599
 600        /* Stop transmit processing */
 601        netif_stop_queue(netdev);
 602
 603        /* Mop up receive && transmit urb's */
 604        usb_kill_urb(kingsun->tx_urb);
 605        usb_free_urb(kingsun->tx_urb);
 606        kingsun->tx_urb = NULL;
 607
 608        usb_kill_urb(kingsun->speed_urb);
 609        usb_free_urb(kingsun->speed_urb);
 610        kingsun->speed_urb = NULL;
 611
 612        usb_kill_urb(kingsun->rx_urb);
 613        usb_free_urb(kingsun->rx_urb);
 614        kingsun->rx_urb = NULL;
 615
 616        kfree_skb(kingsun->rx_unwrap_buff.skb);
 617        kingsun->rx_unwrap_buff.skb = NULL;
 618        kingsun->rx_unwrap_buff.head = NULL;
 619        kingsun->rx_unwrap_buff.in_frame = FALSE;
 620        kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
 621        kingsun->receiving = 0;
 622
 623        /* Stop and remove instance of IrLAP */
 624        if (kingsun->irlap)
 625                irlap_close(kingsun->irlap);
 626
 627        kingsun->irlap = NULL;
 628
 629        return 0;
 630}
 631
 632/*
 633 * IOCTLs : Extra out-of-band network commands...
 634 */
 635static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 636{
 637        struct if_irda_req *irq = (struct if_irda_req *)rq;
 638        struct ks959_cb *kingsun = netdev_priv(netdev);
 639        int ret = 0;
 640
 641        switch (cmd) {
 642        case SIOCSBANDWIDTH:    /* Set bandwidth */
 643                if (!capable(CAP_NET_ADMIN))
 644                        return -EPERM;
 645
 646                /* Check if the device is still there */
 647                if (netif_device_present(kingsun->netdev))
 648                        return ks959_change_speed(kingsun, irq->ifr_baudrate);
 649                break;
 650
 651        case SIOCSMEDIABUSY:    /* Set media busy */
 652                if (!capable(CAP_NET_ADMIN))
 653                        return -EPERM;
 654
 655                /* Check if the IrDA stack is still there */
 656                if (netif_running(kingsun->netdev))
 657                        irda_device_set_media_busy(kingsun->netdev, TRUE);
 658                break;
 659
 660        case SIOCGRECEIVING:
 661                /* Only approximately true */
 662                irq->ifr_receiving = kingsun->receiving;
 663                break;
 664
 665        default:
 666                ret = -EOPNOTSUPP;
 667        }
 668
 669        return ret;
 670}
 671
 672static const struct net_device_ops ks959_ops = {
 673        .ndo_start_xmit = ks959_hard_xmit,
 674        .ndo_open       = ks959_net_open,
 675        .ndo_stop       = ks959_net_close,
 676        .ndo_do_ioctl   = ks959_net_ioctl,
 677};
 678/*
 679 * This routine is called by the USB subsystem for each new device
 680 * in the system. We need to check if the device is ours, and in
 681 * this case start handling it.
 682 */
 683static int ks959_probe(struct usb_interface *intf,
 684                       const struct usb_device_id *id)
 685{
 686        struct usb_device *dev = interface_to_usbdev(intf);
 687        struct ks959_cb *kingsun = NULL;
 688        struct net_device *net = NULL;
 689        int ret = -ENOMEM;
 690
 691        /* Allocate network device container. */
 692        net = alloc_irdadev(sizeof(*kingsun));
 693        if (!net)
 694                goto err_out1;
 695
 696        SET_NETDEV_DEV(net, &intf->dev);
 697        kingsun = netdev_priv(net);
 698        kingsun->netdev = net;
 699        kingsun->usbdev = dev;
 700        kingsun->irlap = NULL;
 701        kingsun->tx_setuprequest = NULL;
 702        kingsun->tx_urb = NULL;
 703        kingsun->tx_buf_clear = NULL;
 704        kingsun->tx_buf_xored = NULL;
 705        kingsun->tx_buf_clear_used = 0;
 706        kingsun->tx_buf_clear_sent = 0;
 707
 708        kingsun->rx_setuprequest = NULL;
 709        kingsun->rx_urb = NULL;
 710        kingsun->rx_buf = NULL;
 711        kingsun->rx_variable_xormask = 0;
 712        kingsun->rx_unwrap_buff.in_frame = FALSE;
 713        kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
 714        kingsun->rx_unwrap_buff.skb = NULL;
 715        kingsun->receiving = 0;
 716        spin_lock_init(&kingsun->lock);
 717
 718        kingsun->speed_setuprequest = NULL;
 719        kingsun->speed_urb = NULL;
 720        kingsun->speedparams.baudrate = 0;
 721
 722        /* Allocate input buffer */
 723        kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL);
 724        if (!kingsun->rx_buf)
 725                goto free_mem;
 726
 727        /* Allocate input setup packet */
 728        kingsun->rx_setuprequest =
 729            kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
 730        if (!kingsun->rx_setuprequest)
 731                goto free_mem;
 732        kingsun->rx_setuprequest->bRequestType =
 733            USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
 734        kingsun->rx_setuprequest->bRequest = KINGSUN_REQ_RECV;
 735        kingsun->rx_setuprequest->wValue = cpu_to_le16(0x0200);
 736        kingsun->rx_setuprequest->wIndex = 0;
 737        kingsun->rx_setuprequest->wLength = cpu_to_le16(KINGSUN_RCV_FIFO_SIZE);
 738
 739        /* Allocate output buffer */
 740        kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL);
 741        if (!kingsun->tx_buf_clear)
 742                goto free_mem;
 743        kingsun->tx_buf_xored = kmalloc(KINGSUN_SND_PACKET_SIZE, GFP_KERNEL);
 744        if (!kingsun->tx_buf_xored)
 745                goto free_mem;
 746
 747        /* Allocate and initialize output setup packet */
 748        kingsun->tx_setuprequest =
 749            kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
 750        if (!kingsun->tx_setuprequest)
 751                goto free_mem;
 752        kingsun->tx_setuprequest->bRequestType =
 753            USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
 754        kingsun->tx_setuprequest->bRequest = KINGSUN_REQ_SEND;
 755        kingsun->tx_setuprequest->wValue = 0;
 756        kingsun->tx_setuprequest->wIndex = 0;
 757        kingsun->tx_setuprequest->wLength = 0;
 758
 759        /* Allocate and initialize speed setup packet */
 760        kingsun->speed_setuprequest =
 761            kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
 762        if (!kingsun->speed_setuprequest)
 763                goto free_mem;
 764        kingsun->speed_setuprequest->bRequestType =
 765            USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
 766        kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND;
 767        kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200);
 768        kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001);
 769        kingsun->speed_setuprequest->wLength =
 770            cpu_to_le16(sizeof(struct ks959_speedparams));
 771
 772        printk(KERN_INFO "KingSun KS-959 IRDA/USB found at address %d, "
 773               "Vendor: %x, Product: %x\n",
 774               dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
 775               le16_to_cpu(dev->descriptor.idProduct));
 776
 777        /* Initialize QoS for this device */
 778        irda_init_max_qos_capabilies(&kingsun->qos);
 779
 780        /* Baud rates known to be supported. Please uncomment if devices (other
 781           than a SonyEriccson K300 phone) can be shown to support higher speed
 782           with this dongle.
 783         */
 784        kingsun->qos.baud_rate.bits =
 785            IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600;
 786        kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
 787        irda_qos_bits_to_value(&kingsun->qos);
 788
 789        /* Override the network functions we need to use */
 790        net->netdev_ops = &ks959_ops;
 791
 792        ret = register_netdev(net);
 793        if (ret != 0)
 794                goto free_mem;
 795
 796        dev_info(&net->dev, "IrDA: Registered KingSun KS-959 device %s\n",
 797                 net->name);
 798
 799        usb_set_intfdata(intf, kingsun);
 800
 801        /* Situation at this point:
 802           - all work buffers allocated
 803           - setup requests pre-filled
 804           - urbs not allocated, set to NULL
 805           - max rx packet known (is KINGSUN_FIFO_SIZE)
 806           - unwrap state machine (partially) initialized, but skb == NULL
 807         */
 808
 809        return 0;
 810
 811      free_mem:
 812        kfree(kingsun->speed_setuprequest);
 813        kfree(kingsun->tx_setuprequest);
 814        kfree(kingsun->tx_buf_xored);
 815        kfree(kingsun->tx_buf_clear);
 816        kfree(kingsun->rx_setuprequest);
 817        kfree(kingsun->rx_buf);
 818        free_netdev(net);
 819      err_out1:
 820        return ret;
 821}
 822
 823/*
 824 * The current device is removed, the USB layer tell us to shut it down...
 825 */
 826static void ks959_disconnect(struct usb_interface *intf)
 827{
 828        struct ks959_cb *kingsun = usb_get_intfdata(intf);
 829
 830        if (!kingsun)
 831                return;
 832
 833        unregister_netdev(kingsun->netdev);
 834
 835        /* Mop up receive && transmit urb's */
 836        if (kingsun->speed_urb != NULL) {
 837                usb_kill_urb(kingsun->speed_urb);
 838                usb_free_urb(kingsun->speed_urb);
 839                kingsun->speed_urb = NULL;
 840        }
 841        if (kingsun->tx_urb != NULL) {
 842                usb_kill_urb(kingsun->tx_urb);
 843                usb_free_urb(kingsun->tx_urb);
 844                kingsun->tx_urb = NULL;
 845        }
 846        if (kingsun->rx_urb != NULL) {
 847                usb_kill_urb(kingsun->rx_urb);
 848                usb_free_urb(kingsun->rx_urb);
 849                kingsun->rx_urb = NULL;
 850        }
 851
 852        kfree(kingsun->speed_setuprequest);
 853        kfree(kingsun->tx_setuprequest);
 854        kfree(kingsun->tx_buf_xored);
 855        kfree(kingsun->tx_buf_clear);
 856        kfree(kingsun->rx_setuprequest);
 857        kfree(kingsun->rx_buf);
 858        free_netdev(kingsun->netdev);
 859
 860        usb_set_intfdata(intf, NULL);
 861}
 862
 863#ifdef CONFIG_PM
 864/* USB suspend, so power off the transmitter/receiver */
 865static int ks959_suspend(struct usb_interface *intf, pm_message_t message)
 866{
 867        struct ks959_cb *kingsun = usb_get_intfdata(intf);
 868
 869        netif_device_detach(kingsun->netdev);
 870        if (kingsun->speed_urb != NULL)
 871                usb_kill_urb(kingsun->speed_urb);
 872        if (kingsun->tx_urb != NULL)
 873                usb_kill_urb(kingsun->tx_urb);
 874        if (kingsun->rx_urb != NULL)
 875                usb_kill_urb(kingsun->rx_urb);
 876        return 0;
 877}
 878
 879/* Coming out of suspend, so reset hardware */
 880static int ks959_resume(struct usb_interface *intf)
 881{
 882        struct ks959_cb *kingsun = usb_get_intfdata(intf);
 883
 884        if (kingsun->rx_urb != NULL) {
 885                /* Setup request already filled in ks959_probe */
 886                usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
 887        }
 888        netif_device_attach(kingsun->netdev);
 889
 890        return 0;
 891}
 892#endif
 893
 894/*
 895 * USB device callbacks
 896 */
 897static struct usb_driver irda_driver = {
 898        .name = "ks959-sir",
 899        .probe = ks959_probe,
 900        .disconnect = ks959_disconnect,
 901        .id_table = dongles,
 902#ifdef CONFIG_PM
 903        .suspend = ks959_suspend,
 904        .resume = ks959_resume,
 905#endif
 906};
 907
 908module_usb_driver(irda_driver);
 909
 910MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
 911MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
 912MODULE_LICENSE("GPL");
 913