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