linux/drivers/net/irda/ksdazzle-sir.c
<<
>>
Prefs
   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} __attribute__ ((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
 799/*
 800 * Module insertion
 801 */
 802static int __init ksdazzle_init(void)
 803{
 804        return usb_register(&irda_driver);
 805}
 806
 807module_init(ksdazzle_init);
 808
 809/*
 810 * Module removal
 811 */
 812static void __exit ksdazzle_cleanup(void)
 813{
 814        /* Deregister the driver and remove all pending instances */
 815        usb_deregister(&irda_driver);
 816}
 817
 818module_exit(ksdazzle_cleanup);
 819
 820MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
 821MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun Dazzle");
 822MODULE_LICENSE("GPL");
 823