1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114#include <linux/module.h>
115#include <linux/moduleparam.h>
116#include <linux/kernel.h>
117#include <linux/types.h>
118#include <linux/errno.h>
119#include <linux/slab.h>
120#include <linux/usb.h>
121#include <linux/device.h>
122#include <linux/crc32.h>
123
124#include <asm/unaligned.h>
125#include <asm/byteorder.h>
126#include <linux/uaccess.h>
127
128#include <net/irda/irda.h>
129#include <net/irda/wrapper.h>
130#include <net/irda/crc.h>
131
132#define KS959_VENDOR_ID 0x07d0
133#define KS959_PRODUCT_ID 0x4959
134
135
136static struct usb_device_id dongles[] = {
137
138 {USB_DEVICE(KS959_VENDOR_ID, KS959_PRODUCT_ID)},
139 {}
140};
141
142MODULE_DEVICE_TABLE(usb, dongles);
143
144#define KINGSUN_MTT 0x07
145#define KINGSUN_REQ_RECV 0x01
146#define KINGSUN_REQ_SEND 0x09
147
148#define KINGSUN_RCV_FIFO_SIZE 2048
149#define KINGSUN_SND_FIFO_SIZE 2048
150#define KINGSUN_SND_PACKET_SIZE 256
151
152struct ks959_speedparams {
153 __le32 baudrate;
154 __u8 flags;
155 __u8 reserved[3];
156} __packed;
157
158#define KS_DATA_5_BITS 0x00
159#define KS_DATA_6_BITS 0x01
160#define KS_DATA_7_BITS 0x02
161#define KS_DATA_8_BITS 0x03
162
163#define KS_STOP_BITS_1 0x00
164#define KS_STOP_BITS_2 0x08
165
166#define KS_PAR_DISABLE 0x00
167#define KS_PAR_EVEN 0x10
168#define KS_PAR_ODD 0x30
169#define KS_RESET 0x80
170
171struct ks959_cb {
172 struct usb_device *usbdev;
173 struct net_device *netdev;
174 struct irlap_cb *irlap;
175
176 struct qos_info qos;
177
178 struct usb_ctrlrequest *tx_setuprequest;
179 struct urb *tx_urb;
180 __u8 *tx_buf_clear;
181 unsigned int tx_buf_clear_used;
182 unsigned int tx_buf_clear_sent;
183 __u8 *tx_buf_xored;
184
185 struct usb_ctrlrequest *rx_setuprequest;
186 struct urb *rx_urb;
187 __u8 *rx_buf;
188 __u8 rx_variable_xormask;
189 iobuff_t rx_unwrap_buff;
190
191 struct usb_ctrlrequest *speed_setuprequest;
192 struct urb *speed_urb;
193 struct ks959_speedparams speedparams;
194 unsigned int new_speed;
195
196 spinlock_t lock;
197 int receiving;
198};
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216static unsigned int obfuscate_tx_buffer(const __u8 * buf_cleartext,
217 unsigned int len_cleartext,
218 __u8 * buf_xoredtext,
219 unsigned int len_maxbuf)
220{
221 unsigned int len_xoredtext;
222
223
224 len_xoredtext = ((len_cleartext + 7) & ~0x7) + 0x10;
225 if (len_xoredtext <= len_maxbuf) {
226 static const __u8 lookup_string[] = "wangshuofei19710";
227 __u8 xor_mask;
228
229
230 memset(buf_xoredtext, 0, len_xoredtext);
231
232 xor_mask = lookup_string[(len_cleartext & 0x0f) ^ 0x06] ^ 0x55;
233
234 while (len_cleartext-- > 0) {
235 *buf_xoredtext++ = *buf_cleartext++ ^ xor_mask;
236 }
237 } else {
238 len_xoredtext = 0;
239 }
240 return len_xoredtext;
241}
242
243
244static void ks959_speed_irq(struct urb *urb)
245{
246
247 if (urb->status != 0) {
248 dev_err(&urb->dev->dev,
249 "ks959_speed_irq: urb asynchronously failed - %d\n",
250 urb->status);
251 }
252}
253
254
255static int ks959_change_speed(struct ks959_cb *kingsun, unsigned speed)
256{
257 static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400,
258 57600, 115200, 576000, 1152000, 4000000, 0
259 };
260 int err;
261 unsigned int i;
262
263 if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL)
264 return -ENOMEM;
265
266
267 for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ;
268 if (supported_speeds[i] == 0)
269 return -EOPNOTSUPP;
270
271 memset(&(kingsun->speedparams), 0, sizeof(struct ks959_speedparams));
272 kingsun->speedparams.baudrate = cpu_to_le32(speed);
273 kingsun->speedparams.flags = KS_DATA_8_BITS;
274
275
276 usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev,
277 usb_sndctrlpipe(kingsun->usbdev, 0),
278 (unsigned char *)kingsun->speed_setuprequest,
279 &(kingsun->speedparams),
280 sizeof(struct ks959_speedparams), ks959_speed_irq,
281 kingsun);
282 kingsun->speed_urb->status = 0;
283 err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC);
284
285 return err;
286}
287
288
289static void ks959_send_irq(struct urb *urb);
290static int ks959_submit_tx_fragment(struct ks959_cb *kingsun)
291{
292 unsigned int padlen;
293 unsigned int wraplen;
294 int ret;
295
296
297
298 wraplen = (KINGSUN_SND_PACKET_SIZE & ~0x7) - 0x10;
299 if (wraplen > kingsun->tx_buf_clear_used)
300 wraplen = kingsun->tx_buf_clear_used;
301
302
303
304 padlen = obfuscate_tx_buffer(kingsun->tx_buf_clear, wraplen,
305 kingsun->tx_buf_xored,
306 KINGSUN_SND_PACKET_SIZE);
307
308
309 kingsun->tx_setuprequest->wValue = cpu_to_le16(wraplen);
310 kingsun->tx_setuprequest->wLength = cpu_to_le16(padlen);
311
312 usb_fill_control_urb(kingsun->tx_urb, kingsun->usbdev,
313 usb_sndctrlpipe(kingsun->usbdev, 0),
314 (unsigned char *)kingsun->tx_setuprequest,
315 kingsun->tx_buf_xored, padlen,
316 ks959_send_irq, kingsun);
317 kingsun->tx_urb->status = 0;
318 ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC);
319
320
321 kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0;
322 return ret;
323}
324
325
326static void ks959_send_irq(struct urb *urb)
327{
328 struct ks959_cb *kingsun = urb->context;
329 struct net_device *netdev = kingsun->netdev;
330 int ret = 0;
331
332
333 if (!netif_running(kingsun->netdev)) {
334 dev_err(&kingsun->usbdev->dev,
335 "ks959_send_irq: Network not running!\n");
336 return;
337 }
338
339
340 if (urb->status != 0) {
341 dev_err(&kingsun->usbdev->dev,
342 "ks959_send_irq: urb asynchronously failed - %d\n",
343 urb->status);
344 return;
345 }
346
347 if (kingsun->tx_buf_clear_used > 0) {
348
349 if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) {
350 memmove(kingsun->tx_buf_clear,
351 kingsun->tx_buf_clear +
352 kingsun->tx_buf_clear_sent,
353 kingsun->tx_buf_clear_used -
354 kingsun->tx_buf_clear_sent);
355 }
356 kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent;
357 kingsun->tx_buf_clear_sent = 0;
358
359 if (kingsun->tx_buf_clear_used > 0) {
360
361 if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
362 dev_err(&kingsun->usbdev->dev,
363 "ks959_send_irq: failed tx_urb submit: %d\n",
364 ret);
365 switch (ret) {
366 case -ENODEV:
367 case -EPIPE:
368 break;
369 default:
370 netdev->stats.tx_errors++;
371 netif_start_queue(netdev);
372 }
373 }
374 } else {
375
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
388
389static netdev_tx_t ks959_hard_xmit(struct sk_buff *skb,
390 struct net_device *netdev)
391{
392 struct ks959_cb *kingsun;
393 unsigned int wraplen;
394 int ret = 0;
395
396 netif_stop_queue(netdev);
397
398
399 SKB_LINEAR_ASSERT(skb);
400
401 kingsun = netdev_priv(netdev);
402
403 spin_lock(&kingsun->lock);
404 kingsun->new_speed = irda_get_next_speed(skb);
405
406
407 wraplen =
408 async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE);
409 kingsun->tx_buf_clear_used = wraplen;
410
411 if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
412 dev_err(&kingsun->usbdev->dev,
413 "ks959_hard_xmit: failed tx_urb submit: %d\n", ret);
414 switch (ret) {
415 case -ENODEV:
416 case -EPIPE:
417 break;
418 default:
419 netdev->stats.tx_errors++;
420 netif_start_queue(netdev);
421 }
422 } else {
423 netdev->stats.tx_packets++;
424 netdev->stats.tx_bytes += skb->len;
425
426 }
427
428 dev_kfree_skb(skb);
429 spin_unlock(&kingsun->lock);
430
431 return NETDEV_TX_OK;
432}
433
434
435static void ks959_rcv_irq(struct urb *urb)
436{
437 struct ks959_cb *kingsun = urb->context;
438 int ret;
439
440
441 if (!netif_running(kingsun->netdev)) {
442 kingsun->receiving = 0;
443 return;
444 }
445
446
447 if (urb->status != 0) {
448 dev_err(&kingsun->usbdev->dev,
449 "kingsun_rcv_irq: urb asynchronously failed - %d\n",
450 urb->status);
451 kingsun->receiving = 0;
452 return;
453 }
454
455 if (urb->actual_length > 0) {
456 __u8 *bytes = urb->transfer_buffer;
457 unsigned int i;
458
459 for (i = 0; i < urb->actual_length; i++) {
460
461
462
463
464 kingsun->rx_variable_xormask++;
465 bytes[i] =
466 bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u;
467
468
469
470
471 if (kingsun->rx_variable_xormask != 0) {
472 async_unwrap_char(kingsun->netdev,
473 &kingsun->netdev->stats,
474 &kingsun->rx_unwrap_buff,
475 bytes[i]);
476 }
477 }
478 kingsun->receiving =
479 (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
480 }
481
482
483
484
485
486
487 urb->status = 0;
488 ret = usb_submit_urb(urb, GFP_ATOMIC);
489}
490
491
492
493
494
495
496static int ks959_net_open(struct net_device *netdev)
497{
498 struct ks959_cb *kingsun = netdev_priv(netdev);
499 int err = -ENOMEM;
500 char hwname[16];
501
502
503 kingsun->receiving = 0;
504
505
506 kingsun->rx_unwrap_buff.in_frame = FALSE;
507 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
508 kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU;
509 kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
510 if (!kingsun->rx_unwrap_buff.skb)
511 goto free_mem;
512
513 skb_reserve(kingsun->rx_unwrap_buff.skb, 1);
514 kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data;
515
516 kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
517 if (!kingsun->rx_urb)
518 goto free_mem;
519
520 kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
521 if (!kingsun->tx_urb)
522 goto free_mem;
523
524 kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL);
525 if (!kingsun->speed_urb)
526 goto free_mem;
527
528
529 kingsun->new_speed = 9600;
530 err = ks959_change_speed(kingsun, 9600);
531 if (err < 0)
532 goto free_mem;
533
534
535
536
537
538 sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
539 kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
540 if (!kingsun->irlap) {
541 err = -ENOMEM;
542 dev_err(&kingsun->usbdev->dev, "irlap_open failed\n");
543 goto free_mem;
544 }
545
546
547 usb_fill_control_urb(kingsun->rx_urb, kingsun->usbdev,
548 usb_rcvctrlpipe(kingsun->usbdev, 0),
549 (unsigned char *)kingsun->rx_setuprequest,
550 kingsun->rx_buf, KINGSUN_RCV_FIFO_SIZE,
551 ks959_rcv_irq, kingsun);
552 kingsun->rx_urb->status = 0;
553 err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
554 if (err) {
555 dev_err(&kingsun->usbdev->dev,
556 "first urb-submit failed: %d\n", err);
557 goto close_irlap;
558 }
559
560 netif_start_queue(netdev);
561
562
563
564
565
566
567
568
569
570
571 return 0;
572
573 close_irlap:
574 irlap_close(kingsun->irlap);
575 free_mem:
576 usb_free_urb(kingsun->speed_urb);
577 kingsun->speed_urb = NULL;
578 usb_free_urb(kingsun->tx_urb);
579 kingsun->tx_urb = NULL;
580 usb_free_urb(kingsun->rx_urb);
581 kingsun->rx_urb = NULL;
582 if (kingsun->rx_unwrap_buff.skb) {
583 kfree_skb(kingsun->rx_unwrap_buff.skb);
584 kingsun->rx_unwrap_buff.skb = NULL;
585 kingsun->rx_unwrap_buff.head = NULL;
586 }
587 return err;
588}
589
590
591
592
593
594
595
596static int ks959_net_close(struct net_device *netdev)
597{
598 struct ks959_cb *kingsun = netdev_priv(netdev);
599
600
601 netif_stop_queue(netdev);
602
603
604 usb_kill_urb(kingsun->tx_urb);
605 usb_free_urb(kingsun->tx_urb);
606 kingsun->tx_urb = NULL;
607
608 usb_kill_urb(kingsun->speed_urb);
609 usb_free_urb(kingsun->speed_urb);
610 kingsun->speed_urb = NULL;
611
612 usb_kill_urb(kingsun->rx_urb);
613 usb_free_urb(kingsun->rx_urb);
614 kingsun->rx_urb = NULL;
615
616 kfree_skb(kingsun->rx_unwrap_buff.skb);
617 kingsun->rx_unwrap_buff.skb = NULL;
618 kingsun->rx_unwrap_buff.head = NULL;
619 kingsun->rx_unwrap_buff.in_frame = FALSE;
620 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
621 kingsun->receiving = 0;
622
623
624 if (kingsun->irlap)
625 irlap_close(kingsun->irlap);
626
627 kingsun->irlap = NULL;
628
629 return 0;
630}
631
632
633
634
635static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
636{
637 struct if_irda_req *irq = (struct if_irda_req *)rq;
638 struct ks959_cb *kingsun = netdev_priv(netdev);
639 int ret = 0;
640
641 switch (cmd) {
642 case SIOCSBANDWIDTH:
643 if (!capable(CAP_NET_ADMIN))
644 return -EPERM;
645
646
647 if (netif_device_present(kingsun->netdev))
648 return ks959_change_speed(kingsun, irq->ifr_baudrate);
649 break;
650
651 case SIOCSMEDIABUSY:
652 if (!capable(CAP_NET_ADMIN))
653 return -EPERM;
654
655
656 if (netif_running(kingsun->netdev))
657 irda_device_set_media_busy(kingsun->netdev, TRUE);
658 break;
659
660 case SIOCGRECEIVING:
661
662 irq->ifr_receiving = kingsun->receiving;
663 break;
664
665 default:
666 ret = -EOPNOTSUPP;
667 }
668
669 return ret;
670}
671
672static const struct net_device_ops ks959_ops = {
673 .ndo_start_xmit = ks959_hard_xmit,
674 .ndo_open = ks959_net_open,
675 .ndo_stop = ks959_net_close,
676 .ndo_do_ioctl = ks959_net_ioctl,
677};
678
679
680
681
682
683static int ks959_probe(struct usb_interface *intf,
684 const struct usb_device_id *id)
685{
686 struct usb_device *dev = interface_to_usbdev(intf);
687 struct ks959_cb *kingsun = NULL;
688 struct net_device *net = NULL;
689 int ret = -ENOMEM;
690
691
692 net = alloc_irdadev(sizeof(*kingsun));
693 if (!net)
694 goto err_out1;
695
696 SET_NETDEV_DEV(net, &intf->dev);
697 kingsun = netdev_priv(net);
698 kingsun->netdev = net;
699 kingsun->usbdev = dev;
700 kingsun->irlap = NULL;
701 kingsun->tx_setuprequest = NULL;
702 kingsun->tx_urb = NULL;
703 kingsun->tx_buf_clear = NULL;
704 kingsun->tx_buf_xored = NULL;
705 kingsun->tx_buf_clear_used = 0;
706 kingsun->tx_buf_clear_sent = 0;
707
708 kingsun->rx_setuprequest = NULL;
709 kingsun->rx_urb = NULL;
710 kingsun->rx_buf = NULL;
711 kingsun->rx_variable_xormask = 0;
712 kingsun->rx_unwrap_buff.in_frame = FALSE;
713 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
714 kingsun->rx_unwrap_buff.skb = NULL;
715 kingsun->receiving = 0;
716 spin_lock_init(&kingsun->lock);
717
718 kingsun->speed_setuprequest = NULL;
719 kingsun->speed_urb = NULL;
720 kingsun->speedparams.baudrate = 0;
721
722
723 kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL);
724 if (!kingsun->rx_buf)
725 goto free_mem;
726
727
728 kingsun->rx_setuprequest =
729 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
730 if (!kingsun->rx_setuprequest)
731 goto free_mem;
732 kingsun->rx_setuprequest->bRequestType =
733 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
734 kingsun->rx_setuprequest->bRequest = KINGSUN_REQ_RECV;
735 kingsun->rx_setuprequest->wValue = cpu_to_le16(0x0200);
736 kingsun->rx_setuprequest->wIndex = 0;
737 kingsun->rx_setuprequest->wLength = cpu_to_le16(KINGSUN_RCV_FIFO_SIZE);
738
739
740 kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL);
741 if (!kingsun->tx_buf_clear)
742 goto free_mem;
743 kingsun->tx_buf_xored = kmalloc(KINGSUN_SND_PACKET_SIZE, GFP_KERNEL);
744 if (!kingsun->tx_buf_xored)
745 goto free_mem;
746
747
748 kingsun->tx_setuprequest =
749 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
750 if (!kingsun->tx_setuprequest)
751 goto free_mem;
752 kingsun->tx_setuprequest->bRequestType =
753 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
754 kingsun->tx_setuprequest->bRequest = KINGSUN_REQ_SEND;
755 kingsun->tx_setuprequest->wValue = 0;
756 kingsun->tx_setuprequest->wIndex = 0;
757 kingsun->tx_setuprequest->wLength = 0;
758
759
760 kingsun->speed_setuprequest =
761 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
762 if (!kingsun->speed_setuprequest)
763 goto free_mem;
764 kingsun->speed_setuprequest->bRequestType =
765 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
766 kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND;
767 kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200);
768 kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001);
769 kingsun->speed_setuprequest->wLength =
770 cpu_to_le16(sizeof(struct ks959_speedparams));
771
772 printk(KERN_INFO "KingSun KS-959 IRDA/USB found at address %d, "
773 "Vendor: %x, Product: %x\n",
774 dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
775 le16_to_cpu(dev->descriptor.idProduct));
776
777
778 irda_init_max_qos_capabilies(&kingsun->qos);
779
780
781
782
783
784 kingsun->qos.baud_rate.bits =
785 IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600;
786 kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
787 irda_qos_bits_to_value(&kingsun->qos);
788
789
790 net->netdev_ops = &ks959_ops;
791
792 ret = register_netdev(net);
793 if (ret != 0)
794 goto free_mem;
795
796 dev_info(&net->dev, "IrDA: Registered KingSun KS-959 device %s\n",
797 net->name);
798
799 usb_set_intfdata(intf, kingsun);
800
801
802
803
804
805
806
807
808
809 return 0;
810
811 free_mem:
812 kfree(kingsun->speed_setuprequest);
813 kfree(kingsun->tx_setuprequest);
814 kfree(kingsun->tx_buf_xored);
815 kfree(kingsun->tx_buf_clear);
816 kfree(kingsun->rx_setuprequest);
817 kfree(kingsun->rx_buf);
818 free_netdev(net);
819 err_out1:
820 return ret;
821}
822
823
824
825
826static void ks959_disconnect(struct usb_interface *intf)
827{
828 struct ks959_cb *kingsun = usb_get_intfdata(intf);
829
830 if (!kingsun)
831 return;
832
833 unregister_netdev(kingsun->netdev);
834
835
836 if (kingsun->speed_urb != NULL) {
837 usb_kill_urb(kingsun->speed_urb);
838 usb_free_urb(kingsun->speed_urb);
839 kingsun->speed_urb = NULL;
840 }
841 if (kingsun->tx_urb != NULL) {
842 usb_kill_urb(kingsun->tx_urb);
843 usb_free_urb(kingsun->tx_urb);
844 kingsun->tx_urb = NULL;
845 }
846 if (kingsun->rx_urb != NULL) {
847 usb_kill_urb(kingsun->rx_urb);
848 usb_free_urb(kingsun->rx_urb);
849 kingsun->rx_urb = NULL;
850 }
851
852 kfree(kingsun->speed_setuprequest);
853 kfree(kingsun->tx_setuprequest);
854 kfree(kingsun->tx_buf_xored);
855 kfree(kingsun->tx_buf_clear);
856 kfree(kingsun->rx_setuprequest);
857 kfree(kingsun->rx_buf);
858 free_netdev(kingsun->netdev);
859
860 usb_set_intfdata(intf, NULL);
861}
862
863#ifdef CONFIG_PM
864
865static int ks959_suspend(struct usb_interface *intf, pm_message_t message)
866{
867 struct ks959_cb *kingsun = usb_get_intfdata(intf);
868
869 netif_device_detach(kingsun->netdev);
870 if (kingsun->speed_urb != NULL)
871 usb_kill_urb(kingsun->speed_urb);
872 if (kingsun->tx_urb != NULL)
873 usb_kill_urb(kingsun->tx_urb);
874 if (kingsun->rx_urb != NULL)
875 usb_kill_urb(kingsun->rx_urb);
876 return 0;
877}
878
879
880static int ks959_resume(struct usb_interface *intf)
881{
882 struct ks959_cb *kingsun = usb_get_intfdata(intf);
883
884 if (kingsun->rx_urb != NULL) {
885
886 usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
887 }
888 netif_device_attach(kingsun->netdev);
889
890 return 0;
891}
892#endif
893
894
895
896
897static struct usb_driver irda_driver = {
898 .name = "ks959-sir",
899 .probe = ks959_probe,
900 .disconnect = ks959_disconnect,
901 .id_table = dongles,
902#ifdef CONFIG_PM
903 .suspend = ks959_suspend,
904 .resume = ks959_resume,
905#endif
906};
907
908module_usb_driver(irda_driver);
909
910MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
911MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
912MODULE_LICENSE("GPL");
913