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/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
137static struct usb_device_id dongles[] = {
138
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
150#define KINGSUN_SND_FIFO_SIZE 2048
151#define KINGSUN_SND_PACKET_SIZE 256
152
153struct ks959_speedparams {
154 __le32 baudrate;
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;
174 struct net_device *netdev;
175 struct irlap_cb *irlap;
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
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
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
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
246static void ks959_speed_irq(struct urb *urb)
247{
248
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
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
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
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
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
299
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
305
306 padlen = obfuscate_tx_buffer(kingsun->tx_buf_clear, wraplen,
307 kingsun->tx_buf_xored,
308 KINGSUN_SND_PACKET_SIZE);
309
310
311 kingsun->tx_setuprequest->wValue = cpu_to_le16(wraplen);
312 kingsun->tx_setuprequest->wLength = cpu_to_le16(padlen);
313
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
323 kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0;
324 return ret;
325}
326
327
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
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
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
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
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
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
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
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
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
437static void ks959_rcv_irq(struct urb *urb)
438{
439 struct ks959_cb *kingsun = urb->context;
440 int ret;
441
442
443 if (!netif_running(kingsun->netdev)) {
444 kingsun->receiving = 0;
445 return;
446 }
447
448
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
463
464
465
466 kingsun->rx_variable_xormask++;
467 bytes[i] =
468 bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u;
469
470
471
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
486
487
488
489
490 urb->status = 0;
491 ret = usb_submit_urb(urb, GFP_ATOMIC);
492}
493
494
495
496
497
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
506 kingsun->receiving = 0;
507
508
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
533 kingsun->new_speed = 9600;
534 err = ks959_change_speed(kingsun, 9600);
535 if (err < 0)
536 goto free_mem;
537
538
539
540
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
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
567
568
569
570
571
572
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
596
597
598
599
600static int ks959_net_close(struct net_device *netdev)
601{
602 struct ks959_cb *kingsun = netdev_priv(netdev);
603
604
605 netif_stop_queue(netdev);
606
607
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
628 if (kingsun->irlap)
629 irlap_close(kingsun->irlap);
630
631 kingsun->irlap = NULL;
632
633 return 0;
634}
635
636
637
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:
647 if (!capable(CAP_NET_ADMIN))
648 return -EPERM;
649
650
651 if (netif_device_present(kingsun->netdev))
652 return ks959_change_speed(kingsun, irq->ifr_baudrate);
653 break;
654
655 case SIOCSMEDIABUSY:
656 if (!capable(CAP_NET_ADMIN))
657 return -EPERM;
658
659
660 if (netif_running(kingsun->netdev))
661 irda_device_set_media_busy(kingsun->netdev, TRUE);
662 break;
663
664 case SIOCGRECEIVING:
665
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
684
685
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
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
727 kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL);
728 if (!kingsun->rx_buf)
729 goto free_mem;
730
731
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
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
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
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
782 irda_init_max_qos_capabilies(&kingsun->qos);
783
784
785
786
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
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
806
807
808
809
810
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
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
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
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
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
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
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