OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [irda/] [ks959-sir.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*****************************************************************************
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/module.h>
122
#include <linux/kref.h>
123
#include <linux/usb.h>
124
#include <linux/device.h>
125
#include <linux/crc32.h>
126
 
127
#include <asm/unaligned.h>
128
#include <asm/byteorder.h>
129
#include <asm/uaccess.h>
130
 
131
#include <net/irda/irda.h>
132
#include <net/irda/wrapper.h>
133
#include <net/irda/crc.h>
134
 
135
#define KS959_VENDOR_ID 0x07d0
136
#define KS959_PRODUCT_ID 0x4959
137
 
138
/* These are the currently known USB ids */
139
static struct usb_device_id dongles[] = {
140
        /* KingSun Co,Ltd  IrDA/USB Bridge */
141
        {USB_DEVICE(KS959_VENDOR_ID, KS959_PRODUCT_ID)},
142
        {}
143
};
144
 
145
MODULE_DEVICE_TABLE(usb, dongles);
146
 
147
#define KINGSUN_MTT 0x07
148
#define KINGSUN_REQ_RECV 0x01
149
#define KINGSUN_REQ_SEND 0x09
150
 
151
#define KINGSUN_RCV_FIFO_SIZE    2048   /* Max length we can receive */
152
#define KINGSUN_SND_FIFO_SIZE    2048   /* Max packet we can send */
153
#define KINGSUN_SND_PACKET_SIZE    256  /* Max packet dongle can handle */
154
 
155
struct ks959_speedparams {
156
        __le32 baudrate;        /* baud rate, little endian */
157
        __u8 flags;
158
        __u8 reserved[3];
159
} __attribute__ ((packed));
160
 
161
#define KS_DATA_5_BITS 0x00
162
#define KS_DATA_6_BITS 0x01
163
#define KS_DATA_7_BITS 0x02
164
#define KS_DATA_8_BITS 0x03
165
 
166
#define KS_STOP_BITS_1 0x00
167
#define KS_STOP_BITS_2 0x08
168
 
169
#define KS_PAR_DISABLE    0x00
170
#define KS_PAR_EVEN    0x10
171
#define KS_PAR_ODD    0x30
172
#define KS_RESET    0x80
173
 
174
struct ks959_cb {
175
        struct usb_device *usbdev;      /* init: probe_irda */
176
        struct net_device *netdev;      /* network layer */
177
        struct irlap_cb *irlap; /* The link layer we are binded to */
178
        struct net_device_stats stats;  /* network statistics */
179
        struct qos_info qos;
180
 
181
        struct usb_ctrlrequest *tx_setuprequest;
182
        struct urb *tx_urb;
183
        __u8 *tx_buf_clear;
184
        unsigned int tx_buf_clear_used;
185
        unsigned int tx_buf_clear_sent;
186
        __u8 *tx_buf_xored;
187
 
188
        struct usb_ctrlrequest *rx_setuprequest;
189
        struct urb *rx_urb;
190
        __u8 *rx_buf;
191
        __u8 rx_variable_xormask;
192
        iobuff_t rx_unwrap_buff;
193
        struct timeval rx_time;
194
 
195
        struct usb_ctrlrequest *speed_setuprequest;
196
        struct urb *speed_urb;
197
        struct ks959_speedparams speedparams;
198
        unsigned int new_speed;
199
 
200
        spinlock_t lock;
201
        int receiving;
202
};
203
 
204
/* Procedure to perform the obfuscation/padding expected by the dongle
205
 *
206
 * buf_cleartext    (IN) Cleartext version of the IrDA frame to transmit
207
 * len_cleartext    (IN) Length of the cleartext version of IrDA frame
208
 * buf_xoredtext    (OUT) Obfuscated version of frame built by proc
209
 * len_maxbuf        (OUT) Maximum space available at buf_xoredtext
210
 *
211
 * (return)         length of obfuscated frame with padding
212
 *
213
 * If not enough space (as indicated by len_maxbuf vs. required padding),
214
 * zero is returned
215
 *
216
 * The value of lookup_string is actually a required portion of the algorithm.
217
 * Seems the designer of the dongle wanted to state who exactly is responsible
218
 * for implementing obfuscation. Send your best (or other) wishes to him ]:-)
219
 */
220
static unsigned int obfuscate_tx_buffer(const __u8 * buf_cleartext,
221
                                        unsigned int len_cleartext,
222
                                        __u8 * buf_xoredtext,
223
                                        unsigned int len_maxbuf)
224
{
225
        unsigned int len_xoredtext;
226
 
227
        /* Calculate required length with padding, check for necessary space */
228
        len_xoredtext = ((len_cleartext + 7) & ~0x7) + 0x10;
229
        if (len_xoredtext <= len_maxbuf) {
230
                static const __u8 lookup_string[] = "wangshuofei19710";
231
                __u8 xor_mask;
232
 
233
                /* Unlike the WinXP driver, we *do* clear out the padding */
234
                memset(buf_xoredtext, 0, len_xoredtext);
235
 
236
                xor_mask = lookup_string[(len_cleartext & 0x0f) ^ 0x06] ^ 0x55;
237
 
238
                while (len_cleartext-- > 0) {
239
                        *buf_xoredtext++ = *buf_cleartext++ ^ xor_mask;
240
                }
241
        } else {
242
                len_xoredtext = 0;
243
        }
244
        return len_xoredtext;
245
}
246
 
247
/* Callback transmission routine */
248
static void ks959_speed_irq(struct urb *urb)
249
{
250
        /* unlink, shutdown, unplug, other nasties */
251
        if (urb->status != 0) {
252
                err("ks959_speed_irq: urb asynchronously failed - %d",
253
                    urb->status);
254
        }
255
}
256
 
257
/* Send a control request to change speed of the dongle */
258
static int ks959_change_speed(struct ks959_cb *kingsun, unsigned speed)
259
{
260
        static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400,
261
                57600, 115200, 576000, 1152000, 4000000, 0
262
        };
263
        int err;
264
        unsigned int i;
265
 
266
        if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL)
267
                return -ENOMEM;
268
 
269
        /* Check that requested speed is among the supported ones */
270
        for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ;
271
        if (supported_speeds[i] == 0)
272
                return -EOPNOTSUPP;
273
 
274
        memset(&(kingsun->speedparams), 0, sizeof(struct ks959_speedparams));
275
        kingsun->speedparams.baudrate = cpu_to_le32(speed);
276
        kingsun->speedparams.flags = KS_DATA_8_BITS;
277
 
278
        /* speed_setuprequest pre-filled in ks959_probe */
279
        usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev,
280
                             usb_sndctrlpipe(kingsun->usbdev, 0),
281
                             (unsigned char *)kingsun->speed_setuprequest,
282
                             &(kingsun->speedparams),
283
                             sizeof(struct ks959_speedparams), ks959_speed_irq,
284
                             kingsun);
285
        kingsun->speed_urb->status = 0;
286
        err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC);
287
 
288
        return err;
289
}
290
 
291
/* Submit one fragment of an IrDA frame to the dongle */
292
static void ks959_send_irq(struct urb *urb);
293
static int ks959_submit_tx_fragment(struct ks959_cb *kingsun)
294
{
295
        unsigned int padlen;
296
        unsigned int wraplen;
297
        int ret;
298
 
299
        /* Check whether current plaintext can produce a padded buffer that fits
300
           within the range handled by the dongle */
301
        wraplen = (KINGSUN_SND_PACKET_SIZE & ~0x7) - 0x10;
302
        if (wraplen > kingsun->tx_buf_clear_used)
303
                wraplen = kingsun->tx_buf_clear_used;
304
 
305
        /* Perform dongle obfuscation. Also remove the portion of the frame that
306
           was just obfuscated and will now be sent to the dongle. */
307
        padlen = obfuscate_tx_buffer(kingsun->tx_buf_clear, wraplen,
308
                                     kingsun->tx_buf_xored,
309
                                     KINGSUN_SND_PACKET_SIZE);
310
 
311
        /* Calculate how much data can be transmitted in this urb */
312
        kingsun->tx_setuprequest->wValue = cpu_to_le16(wraplen);
313
        kingsun->tx_setuprequest->wLength = cpu_to_le16(padlen);
314
        /* Rest of the fields were filled in ks959_probe */
315
        usb_fill_control_urb(kingsun->tx_urb, kingsun->usbdev,
316
                             usb_sndctrlpipe(kingsun->usbdev, 0),
317
                             (unsigned char *)kingsun->tx_setuprequest,
318
                             kingsun->tx_buf_xored, padlen,
319
                             ks959_send_irq, kingsun);
320
        kingsun->tx_urb->status = 0;
321
        ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC);
322
 
323
        /* Remember how much data was sent, in order to update at callback */
324
        kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0;
325
        return ret;
326
}
327
 
328
/* Callback transmission routine */
329
static void ks959_send_irq(struct urb *urb)
330
{
331
        struct ks959_cb *kingsun = urb->context;
332
        struct net_device *netdev = kingsun->netdev;
333
        int ret = 0;
334
 
335
        /* in process of stopping, just drop data */
336
        if (!netif_running(kingsun->netdev)) {
337
                err("ks959_send_irq: Network not running!");
338
                return;
339
        }
340
 
341
        /* unlink, shutdown, unplug, other nasties */
342
        if (urb->status != 0) {
343
                err("ks959_send_irq: urb asynchronously failed - %d",
344
                    urb->status);
345
                return;
346
        }
347
 
348
        if (kingsun->tx_buf_clear_used > 0) {
349
                /* Update data remaining to be sent */
350
                if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) {
351
                        memmove(kingsun->tx_buf_clear,
352
                                kingsun->tx_buf_clear +
353
                                kingsun->tx_buf_clear_sent,
354
                                kingsun->tx_buf_clear_used -
355
                                kingsun->tx_buf_clear_sent);
356
                }
357
                kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent;
358
                kingsun->tx_buf_clear_sent = 0;
359
 
360
                if (kingsun->tx_buf_clear_used > 0) {
361
                        /* There is more data to be sent */
362
                        if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
363
                                err("ks959_send_irq: failed tx_urb submit: %d",
364
                                    ret);
365
                                switch (ret) {
366
                                case -ENODEV:
367
                                case -EPIPE:
368
                                        break;
369
                                default:
370
                                        kingsun->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
 */
389
static int ks959_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
390
{
391
        struct ks959_cb *kingsun;
392
        unsigned int wraplen;
393
        int ret = 0;
394
 
395
        if (skb == NULL || netdev == NULL)
396
                return -EINVAL;
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
                err("ks959_hard_xmit: failed tx_urb submit: %d", ret);
415
                switch (ret) {
416
                case -ENODEV:
417
                case -EPIPE:
418
                        break;
419
                default:
420
                        kingsun->stats.tx_errors++;
421
                        netif_start_queue(netdev);
422
                }
423
        } else {
424
                kingsun->stats.tx_packets++;
425
                kingsun->stats.tx_bytes += skb->len;
426
 
427
        }
428
 
429
        dev_kfree_skb(skb);
430
        spin_unlock(&kingsun->lock);
431
 
432
        return ret;
433
}
434
 
435
/* Receive callback function */
436
static void ks959_rcv_irq(struct urb *urb)
437
{
438
        struct ks959_cb *kingsun = urb->context;
439
        int ret;
440
 
441
        /* in process of stopping, just drop data */
442
        if (!netif_running(kingsun->netdev)) {
443
                kingsun->receiving = 0;
444
                return;
445
        }
446
 
447
        /* unlink, shutdown, unplug, other nasties */
448
        if (urb->status != 0) {
449
                err("kingsun_rcv_irq: urb asynchronously failed - %d",
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->stats,
474
                                                  &kingsun->rx_unwrap_buff,
475
                                                  bytes[i]);
476
                        }
477
                }
478
                kingsun->netdev->last_rx = jiffies;
479
                do_gettimeofday(&kingsun->rx_time);
480
                kingsun->receiving =
481
                    (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
482
        }
483
 
484
        /* This urb has already been filled in kingsun_net_open. Setup
485
           packet must be re-filled, but it is assumed that urb keeps the
486
           pointer to the initial setup packet, as well as the payload buffer.
487
           Setup packet is already pre-filled at ks959_probe.
488
         */
489
        urb->status = 0;
490
        ret = usb_submit_urb(urb, GFP_ATOMIC);
491
}
492
 
493
/*
494
 * Function kingsun_net_open (dev)
495
 *
496
 *    Network device is taken up. Usually this is done by "ifconfig irda0 up"
497
 */
498
static int ks959_net_open(struct net_device *netdev)
499
{
500
        struct ks959_cb *kingsun = netdev_priv(netdev);
501
        int err = -ENOMEM;
502
        char hwname[16];
503
 
504
        /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
505
        kingsun->receiving = 0;
506
 
507
        /* Initialize for SIR to copy data directly into skb.  */
508
        kingsun->rx_unwrap_buff.in_frame = FALSE;
509
        kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
510
        kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU;
511
        kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
512
        if (!kingsun->rx_unwrap_buff.skb)
513
                goto free_mem;
514
 
515
        skb_reserve(kingsun->rx_unwrap_buff.skb, 1);
516
        kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data;
517
        do_gettimeofday(&kingsun->rx_time);
518
 
519
        kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
520
        if (!kingsun->rx_urb)
521
                goto free_mem;
522
 
523
        kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
524
        if (!kingsun->tx_urb)
525
                goto free_mem;
526
 
527
        kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL);
528
        if (!kingsun->speed_urb)
529
                goto free_mem;
530
 
531
        /* Initialize speed for dongle */
532
        kingsun->new_speed = 9600;
533
        err = ks959_change_speed(kingsun, 9600);
534
        if (err < 0)
535
                goto free_mem;
536
 
537
        /*
538
         * Now that everything should be initialized properly,
539
         * Open new IrLAP layer instance to take care of us...
540
         */
541
        sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
542
        kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
543
        if (!kingsun->irlap) {
544
                err("ks959-sir: irlap_open failed");
545
                goto free_mem;
546
        }
547
 
548
        /* Start reception. Setup request already pre-filled in ks959_probe */
549
        usb_fill_control_urb(kingsun->rx_urb, kingsun->usbdev,
550
                             usb_rcvctrlpipe(kingsun->usbdev, 0),
551
                             (unsigned char *)kingsun->rx_setuprequest,
552
                             kingsun->rx_buf, KINGSUN_RCV_FIFO_SIZE,
553
                             ks959_rcv_irq, kingsun);
554
        kingsun->rx_urb->status = 0;
555
        err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
556
        if (err) {
557
                err("ks959-sir: first urb-submit failed: %d", err);
558
                goto close_irlap;
559
        }
560
 
561
        netif_start_queue(netdev);
562
 
563
        /* Situation at this point:
564
           - all work buffers allocated
565
           - urbs allocated and ready to fill
566
           - max rx packet known (in max_rx)
567
           - unwrap state machine initialized, in state outside of any frame
568
           - receive request in progress
569
           - IrLAP layer started, about to hand over packets to send
570
         */
571
 
572
        return 0;
573
 
574
      close_irlap:
575
        irlap_close(kingsun->irlap);
576
      free_mem:
577
        usb_free_urb(kingsun->speed_urb);
578
        kingsun->speed_urb = NULL;
579
        usb_free_urb(kingsun->tx_urb);
580
        kingsun->tx_urb = NULL;
581
        usb_free_urb(kingsun->rx_urb);
582
        kingsun->rx_urb = NULL;
583
        if (kingsun->rx_unwrap_buff.skb) {
584
                kfree_skb(kingsun->rx_unwrap_buff.skb);
585
                kingsun->rx_unwrap_buff.skb = NULL;
586
                kingsun->rx_unwrap_buff.head = NULL;
587
        }
588
        return err;
589
}
590
 
591
/*
592
 * Function kingsun_net_close (kingsun)
593
 *
594
 *    Network device is taken down. Usually this is done by
595
 *    "ifconfig irda0 down"
596
 */
597
static int ks959_net_close(struct net_device *netdev)
598
{
599
        struct ks959_cb *kingsun = netdev_priv(netdev);
600
 
601
        /* Stop transmit processing */
602
        netif_stop_queue(netdev);
603
 
604
        /* Mop up receive && transmit urb's */
605
        usb_kill_urb(kingsun->tx_urb);
606
        usb_free_urb(kingsun->tx_urb);
607
        kingsun->tx_urb = NULL;
608
 
609
        usb_kill_urb(kingsun->speed_urb);
610
        usb_free_urb(kingsun->speed_urb);
611
        kingsun->speed_urb = NULL;
612
 
613
        usb_kill_urb(kingsun->rx_urb);
614
        usb_free_urb(kingsun->rx_urb);
615
        kingsun->rx_urb = NULL;
616
 
617
        kfree_skb(kingsun->rx_unwrap_buff.skb);
618
        kingsun->rx_unwrap_buff.skb = NULL;
619
        kingsun->rx_unwrap_buff.head = NULL;
620
        kingsun->rx_unwrap_buff.in_frame = FALSE;
621
        kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
622
        kingsun->receiving = 0;
623
 
624
        /* Stop and remove instance of IrLAP */
625
        if (kingsun->irlap)
626
                irlap_close(kingsun->irlap);
627
 
628
        kingsun->irlap = NULL;
629
 
630
        return 0;
631
}
632
 
633
/*
634
 * IOCTLs : Extra out-of-band network commands...
635
 */
636
static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
637
{
638
        struct if_irda_req *irq = (struct if_irda_req *)rq;
639
        struct ks959_cb *kingsun = netdev_priv(netdev);
640
        int ret = 0;
641
 
642
        switch (cmd) {
643
        case SIOCSBANDWIDTH:    /* Set bandwidth */
644
                if (!capable(CAP_NET_ADMIN))
645
                        return -EPERM;
646
 
647
                /* Check if the device is still there */
648
                if (netif_device_present(kingsun->netdev))
649
                        return ks959_change_speed(kingsun, irq->ifr_baudrate);
650
                break;
651
 
652
        case SIOCSMEDIABUSY:    /* Set media busy */
653
                if (!capable(CAP_NET_ADMIN))
654
                        return -EPERM;
655
 
656
                /* Check if the IrDA stack is still there */
657
                if (netif_running(kingsun->netdev))
658
                        irda_device_set_media_busy(kingsun->netdev, TRUE);
659
                break;
660
 
661
        case SIOCGRECEIVING:
662
                /* Only approximately true */
663
                irq->ifr_receiving = kingsun->receiving;
664
                break;
665
 
666
        default:
667
                ret = -EOPNOTSUPP;
668
        }
669
 
670
        return ret;
671
}
672
 
673
/*
674
 * Get device stats (for /proc/net/dev and ifconfig)
675
 */
676
static struct net_device_stats *ks959_net_get_stats(struct net_device *netdev)
677
{
678
        struct ks959_cb *kingsun = netdev_priv(netdev);
679
        return &kingsun->stats;
680
}
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
 */
687
static 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->hard_start_xmit = ks959_hard_xmit;
795
        net->open = ks959_net_open;
796
        net->stop = ks959_net_close;
797
        net->get_stats = ks959_net_get_stats;
798
        net->do_ioctl = ks959_net_ioctl;
799
 
800
        ret = register_netdev(net);
801
        if (ret != 0)
802
                goto free_mem;
803
 
804
        info("IrDA: Registered KingSun KS-959 device %s", net->name);
805
 
806
        usb_set_intfdata(intf, kingsun);
807
 
808
        /* Situation at this point:
809
           - all work buffers allocated
810
           - setup requests pre-filled
811
           - urbs not allocated, set to NULL
812
           - max rx packet known (is KINGSUN_FIFO_SIZE)
813
           - unwrap state machine (partially) initialized, but skb == NULL
814
         */
815
 
816
        return 0;
817
 
818
      free_mem:
819
        kfree(kingsun->speed_setuprequest);
820
        kfree(kingsun->tx_setuprequest);
821
        kfree(kingsun->tx_buf_xored);
822
        kfree(kingsun->tx_buf_clear);
823
        kfree(kingsun->rx_setuprequest);
824
        kfree(kingsun->rx_buf);
825
        free_netdev(net);
826
      err_out1:
827
        return ret;
828
}
829
 
830
/*
831
 * The current device is removed, the USB layer tell us to shut it down...
832
 */
833
static void ks959_disconnect(struct usb_interface *intf)
834
{
835
        struct ks959_cb *kingsun = usb_get_intfdata(intf);
836
 
837
        if (!kingsun)
838
                return;
839
 
840
        unregister_netdev(kingsun->netdev);
841
 
842
        /* Mop up receive && transmit urb's */
843
        if (kingsun->speed_urb != NULL) {
844
                usb_kill_urb(kingsun->speed_urb);
845
                usb_free_urb(kingsun->speed_urb);
846
                kingsun->speed_urb = NULL;
847
        }
848
        if (kingsun->tx_urb != NULL) {
849
                usb_kill_urb(kingsun->tx_urb);
850
                usb_free_urb(kingsun->tx_urb);
851
                kingsun->tx_urb = NULL;
852
        }
853
        if (kingsun->rx_urb != NULL) {
854
                usb_kill_urb(kingsun->rx_urb);
855
                usb_free_urb(kingsun->rx_urb);
856
                kingsun->rx_urb = NULL;
857
        }
858
 
859
        kfree(kingsun->speed_setuprequest);
860
        kfree(kingsun->tx_setuprequest);
861
        kfree(kingsun->tx_buf_xored);
862
        kfree(kingsun->tx_buf_clear);
863
        kfree(kingsun->rx_setuprequest);
864
        kfree(kingsun->rx_buf);
865
        free_netdev(kingsun->netdev);
866
 
867
        usb_set_intfdata(intf, NULL);
868
}
869
 
870
#ifdef CONFIG_PM
871
/* USB suspend, so power off the transmitter/receiver */
872
static int ks959_suspend(struct usb_interface *intf, pm_message_t message)
873
{
874
        struct ks959_cb *kingsun = usb_get_intfdata(intf);
875
 
876
        netif_device_detach(kingsun->netdev);
877
        if (kingsun->speed_urb != NULL)
878
                usb_kill_urb(kingsun->speed_urb);
879
        if (kingsun->tx_urb != NULL)
880
                usb_kill_urb(kingsun->tx_urb);
881
        if (kingsun->rx_urb != NULL)
882
                usb_kill_urb(kingsun->rx_urb);
883
        return 0;
884
}
885
 
886
/* Coming out of suspend, so reset hardware */
887
static int ks959_resume(struct usb_interface *intf)
888
{
889
        struct ks959_cb *kingsun = usb_get_intfdata(intf);
890
 
891
        if (kingsun->rx_urb != NULL) {
892
                /* Setup request already filled in ks959_probe */
893
                usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
894
        }
895
        netif_device_attach(kingsun->netdev);
896
 
897
        return 0;
898
}
899
#endif
900
 
901
/*
902
 * USB device callbacks
903
 */
904
static struct usb_driver irda_driver = {
905
        .name = "ks959-sir",
906
        .probe = ks959_probe,
907
        .disconnect = ks959_disconnect,
908
        .id_table = dongles,
909
#ifdef CONFIG_PM
910
        .suspend = ks959_suspend,
911
        .resume = ks959_resume,
912
#endif
913
};
914
 
915
/*
916
 * Module insertion
917
 */
918
static int __init ks959_init(void)
919
{
920
        return usb_register(&irda_driver);
921
}
922
 
923
module_init(ks959_init);
924
 
925
/*
926
 * Module removal
927
 */
928
static void __exit ks959_cleanup(void)
929
{
930
        /* Deregister the driver and remove all pending instances */
931
        usb_deregister(&irda_driver);
932
}
933
 
934
module_exit(ks959_cleanup);
935
 
936
MODULE_AUTHOR("Alex VillacĂ­s Lasso <a_villacis@palosanto.com>");
937
MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
938
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.