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} __attribute__ ((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 err("ks959_speed_irq: urb asynchronously failed - %d",
251 urb->status);
252 }
253}
254
255
256static int ks959_change_speed(struct ks959_cb *kingsun, unsigned speed)
257{
258 static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400,
259 57600, 115200, 576000, 1152000, 4000000, 0
260 };
261 int err;
262 unsigned int i;
263
264 if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL)
265 return -ENOMEM;
266
267
268 for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ;
269 if (supported_speeds[i] == 0)
270 return -EOPNOTSUPP;
271
272 memset(&(kingsun->speedparams), 0, sizeof(struct ks959_speedparams));
273 kingsun->speedparams.baudrate = cpu_to_le32(speed);
274 kingsun->speedparams.flags = KS_DATA_8_BITS;
275
276
277 usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev,
278 usb_sndctrlpipe(kingsun->usbdev, 0),
279 (unsigned char *)kingsun->speed_setuprequest,
280 &(kingsun->speedparams),
281 sizeof(struct ks959_speedparams), ks959_speed_irq,
282 kingsun);
283 kingsun->speed_urb->status = 0;
284 err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC);
285
286 return err;
287}
288
289
290static void ks959_send_irq(struct urb *urb);
291static int ks959_submit_tx_fragment(struct ks959_cb *kingsun)
292{
293 unsigned int padlen;
294 unsigned int wraplen;
295 int ret;
296
297
298
299 wraplen = (KINGSUN_SND_PACKET_SIZE & ~0x7) - 0x10;
300 if (wraplen > kingsun->tx_buf_clear_used)
301 wraplen = kingsun->tx_buf_clear_used;
302
303
304
305 padlen = obfuscate_tx_buffer(kingsun->tx_buf_clear, wraplen,
306 kingsun->tx_buf_xored,
307 KINGSUN_SND_PACKET_SIZE);
308
309
310 kingsun->tx_setuprequest->wValue = cpu_to_le16(wraplen);
311 kingsun->tx_setuprequest->wLength = cpu_to_le16(padlen);
312
313 usb_fill_control_urb(kingsun->tx_urb, kingsun->usbdev,
314 usb_sndctrlpipe(kingsun->usbdev, 0),
315 (unsigned char *)kingsun->tx_setuprequest,
316 kingsun->tx_buf_xored, padlen,
317 ks959_send_irq, kingsun);
318 kingsun->tx_urb->status = 0;
319 ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC);
320
321
322 kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0;
323 return ret;
324}
325
326
327static void ks959_send_irq(struct urb *urb)
328{
329 struct ks959_cb *kingsun = urb->context;
330 struct net_device *netdev = kingsun->netdev;
331 int ret = 0;
332
333
334 if (!netif_running(kingsun->netdev)) {
335 err("ks959_send_irq: Network not running!");
336 return;
337 }
338
339
340 if (urb->status != 0) {
341 err("ks959_send_irq: urb asynchronously failed - %d",
342 urb->status);
343 return;
344 }
345
346 if (kingsun->tx_buf_clear_used > 0) {
347
348 if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) {
349 memmove(kingsun->tx_buf_clear,
350 kingsun->tx_buf_clear +
351 kingsun->tx_buf_clear_sent,
352 kingsun->tx_buf_clear_used -
353 kingsun->tx_buf_clear_sent);
354 }
355 kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent;
356 kingsun->tx_buf_clear_sent = 0;
357
358 if (kingsun->tx_buf_clear_used > 0) {
359
360 if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
361 err("ks959_send_irq: failed tx_urb submit: %d",
362 ret);
363 switch (ret) {
364 case -ENODEV:
365 case -EPIPE:
366 break;
367 default:
368 netdev->stats.tx_errors++;
369 netif_start_queue(netdev);
370 }
371 }
372 } else {
373
374 if (kingsun->new_speed != -1 &&
375 cpu_to_le32(kingsun->new_speed) !=
376 kingsun->speedparams.baudrate)
377 ks959_change_speed(kingsun, kingsun->new_speed);
378
379 netif_wake_queue(netdev);
380 }
381 }
382}
383
384
385
386
387static netdev_tx_t ks959_hard_xmit(struct sk_buff *skb,
388 struct net_device *netdev)
389{
390 struct ks959_cb *kingsun;
391 unsigned int wraplen;
392 int ret = 0;
393
394 netif_stop_queue(netdev);
395
396
397 SKB_LINEAR_ASSERT(skb);
398
399 kingsun = netdev_priv(netdev);
400
401 spin_lock(&kingsun->lock);
402 kingsun->new_speed = irda_get_next_speed(skb);
403
404
405 wraplen =
406 async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE);
407 kingsun->tx_buf_clear_used = wraplen;
408
409 if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
410 err("ks959_hard_xmit: failed tx_urb submit: %d", ret);
411 switch (ret) {
412 case -ENODEV:
413 case -EPIPE:
414 break;
415 default:
416 netdev->stats.tx_errors++;
417 netif_start_queue(netdev);
418 }
419 } else {
420 netdev->stats.tx_packets++;
421 netdev->stats.tx_bytes += skb->len;
422
423 }
424
425 dev_kfree_skb(skb);
426 spin_unlock(&kingsun->lock);
427
428 return NETDEV_TX_OK;
429}
430
431
432static void ks959_rcv_irq(struct urb *urb)
433{
434 struct ks959_cb *kingsun = urb->context;
435 int ret;
436
437
438 if (!netif_running(kingsun->netdev)) {
439 kingsun->receiving = 0;
440 return;
441 }
442
443
444 if (urb->status != 0) {
445 err("kingsun_rcv_irq: urb asynchronously failed - %d",
446 urb->status);
447 kingsun->receiving = 0;
448 return;
449 }
450
451 if (urb->actual_length > 0) {
452 __u8 *bytes = urb->transfer_buffer;
453 unsigned int i;
454
455 for (i = 0; i < urb->actual_length; i++) {
456
457
458
459
460 kingsun->rx_variable_xormask++;
461 bytes[i] =
462 bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u;
463
464
465
466
467 if (kingsun->rx_variable_xormask != 0) {
468 async_unwrap_char(kingsun->netdev,
469 &kingsun->netdev->stats,
470 &kingsun->rx_unwrap_buff,
471 bytes[i]);
472 }
473 }
474 do_gettimeofday(&kingsun->rx_time);
475 kingsun->receiving =
476 (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
477 }
478
479
480
481
482
483
484 urb->status = 0;
485 ret = usb_submit_urb(urb, GFP_ATOMIC);
486}
487
488
489
490
491
492
493static int ks959_net_open(struct net_device *netdev)
494{
495 struct ks959_cb *kingsun = netdev_priv(netdev);
496 int err = -ENOMEM;
497 char hwname[16];
498
499
500 kingsun->receiving = 0;
501
502
503 kingsun->rx_unwrap_buff.in_frame = FALSE;
504 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
505 kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU;
506 kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
507 if (!kingsun->rx_unwrap_buff.skb)
508 goto free_mem;
509
510 skb_reserve(kingsun->rx_unwrap_buff.skb, 1);
511 kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data;
512 do_gettimeofday(&kingsun->rx_time);
513
514 kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
515 if (!kingsun->rx_urb)
516 goto free_mem;
517
518 kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
519 if (!kingsun->tx_urb)
520 goto free_mem;
521
522 kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL);
523 if (!kingsun->speed_urb)
524 goto free_mem;
525
526
527 kingsun->new_speed = 9600;
528 err = ks959_change_speed(kingsun, 9600);
529 if (err < 0)
530 goto free_mem;
531
532
533
534
535
536 sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
537 kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
538 if (!kingsun->irlap) {
539 err("ks959-sir: irlap_open failed");
540 goto free_mem;
541 }
542
543
544 usb_fill_control_urb(kingsun->rx_urb, kingsun->usbdev,
545 usb_rcvctrlpipe(kingsun->usbdev, 0),
546 (unsigned char *)kingsun->rx_setuprequest,
547 kingsun->rx_buf, KINGSUN_RCV_FIFO_SIZE,
548 ks959_rcv_irq, kingsun);
549 kingsun->rx_urb->status = 0;
550 err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
551 if (err) {
552 err("ks959-sir: first urb-submit failed: %d", err);
553 goto close_irlap;
554 }
555
556 netif_start_queue(netdev);
557
558
559
560
561
562
563
564
565
566
567 return 0;
568
569 close_irlap:
570 irlap_close(kingsun->irlap);
571 free_mem:
572 usb_free_urb(kingsun->speed_urb);
573 kingsun->speed_urb = NULL;
574 usb_free_urb(kingsun->tx_urb);
575 kingsun->tx_urb = NULL;
576 usb_free_urb(kingsun->rx_urb);
577 kingsun->rx_urb = NULL;
578 if (kingsun->rx_unwrap_buff.skb) {
579 kfree_skb(kingsun->rx_unwrap_buff.skb);
580 kingsun->rx_unwrap_buff.skb = NULL;
581 kingsun->rx_unwrap_buff.head = NULL;
582 }
583 return err;
584}
585
586
587
588
589
590
591
592static int ks959_net_close(struct net_device *netdev)
593{
594 struct ks959_cb *kingsun = netdev_priv(netdev);
595
596
597 netif_stop_queue(netdev);
598
599
600 usb_kill_urb(kingsun->tx_urb);
601 usb_free_urb(kingsun->tx_urb);
602 kingsun->tx_urb = NULL;
603
604 usb_kill_urb(kingsun->speed_urb);
605 usb_free_urb(kingsun->speed_urb);
606 kingsun->speed_urb = NULL;
607
608 usb_kill_urb(kingsun->rx_urb);
609 usb_free_urb(kingsun->rx_urb);
610 kingsun->rx_urb = NULL;
611
612 kfree_skb(kingsun->rx_unwrap_buff.skb);
613 kingsun->rx_unwrap_buff.skb = NULL;
614 kingsun->rx_unwrap_buff.head = NULL;
615 kingsun->rx_unwrap_buff.in_frame = FALSE;
616 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
617 kingsun->receiving = 0;
618
619
620 if (kingsun->irlap)
621 irlap_close(kingsun->irlap);
622
623 kingsun->irlap = NULL;
624
625 return 0;
626}
627
628
629
630
631static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
632{
633 struct if_irda_req *irq = (struct if_irda_req *)rq;
634 struct ks959_cb *kingsun = netdev_priv(netdev);
635 int ret = 0;
636
637 switch (cmd) {
638 case SIOCSBANDWIDTH:
639 if (!capable(CAP_NET_ADMIN))
640 return -EPERM;
641
642
643 if (netif_device_present(kingsun->netdev))
644 return ks959_change_speed(kingsun, irq->ifr_baudrate);
645 break;
646
647 case SIOCSMEDIABUSY:
648 if (!capable(CAP_NET_ADMIN))
649 return -EPERM;
650
651
652 if (netif_running(kingsun->netdev))
653 irda_device_set_media_busy(kingsun->netdev, TRUE);
654 break;
655
656 case SIOCGRECEIVING:
657
658 irq->ifr_receiving = kingsun->receiving;
659 break;
660
661 default:
662 ret = -EOPNOTSUPP;
663 }
664
665 return ret;
666}
667
668static const struct net_device_ops ks959_ops = {
669 .ndo_start_xmit = ks959_hard_xmit,
670 .ndo_open = ks959_net_open,
671 .ndo_stop = ks959_net_close,
672 .ndo_do_ioctl = ks959_net_ioctl,
673};
674
675
676
677
678
679static int ks959_probe(struct usb_interface *intf,
680 const struct usb_device_id *id)
681{
682 struct usb_device *dev = interface_to_usbdev(intf);
683 struct ks959_cb *kingsun = NULL;
684 struct net_device *net = NULL;
685 int ret = -ENOMEM;
686
687
688 net = alloc_irdadev(sizeof(*kingsun));
689 if (!net)
690 goto err_out1;
691
692 SET_NETDEV_DEV(net, &intf->dev);
693 kingsun = netdev_priv(net);
694 kingsun->netdev = net;
695 kingsun->usbdev = dev;
696 kingsun->irlap = NULL;
697 kingsun->tx_setuprequest = NULL;
698 kingsun->tx_urb = NULL;
699 kingsun->tx_buf_clear = NULL;
700 kingsun->tx_buf_xored = NULL;
701 kingsun->tx_buf_clear_used = 0;
702 kingsun->tx_buf_clear_sent = 0;
703
704 kingsun->rx_setuprequest = NULL;
705 kingsun->rx_urb = NULL;
706 kingsun->rx_buf = NULL;
707 kingsun->rx_variable_xormask = 0;
708 kingsun->rx_unwrap_buff.in_frame = FALSE;
709 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
710 kingsun->rx_unwrap_buff.skb = NULL;
711 kingsun->receiving = 0;
712 spin_lock_init(&kingsun->lock);
713
714 kingsun->speed_setuprequest = NULL;
715 kingsun->speed_urb = NULL;
716 kingsun->speedparams.baudrate = 0;
717
718
719 kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL);
720 if (!kingsun->rx_buf)
721 goto free_mem;
722
723
724 kingsun->rx_setuprequest =
725 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
726 if (!kingsun->rx_setuprequest)
727 goto free_mem;
728 kingsun->rx_setuprequest->bRequestType =
729 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
730 kingsun->rx_setuprequest->bRequest = KINGSUN_REQ_RECV;
731 kingsun->rx_setuprequest->wValue = cpu_to_le16(0x0200);
732 kingsun->rx_setuprequest->wIndex = 0;
733 kingsun->rx_setuprequest->wLength = cpu_to_le16(KINGSUN_RCV_FIFO_SIZE);
734
735
736 kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL);
737 if (!kingsun->tx_buf_clear)
738 goto free_mem;
739 kingsun->tx_buf_xored = kmalloc(KINGSUN_SND_PACKET_SIZE, GFP_KERNEL);
740 if (!kingsun->tx_buf_xored)
741 goto free_mem;
742
743
744 kingsun->tx_setuprequest =
745 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
746 if (!kingsun->tx_setuprequest)
747 goto free_mem;
748 kingsun->tx_setuprequest->bRequestType =
749 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
750 kingsun->tx_setuprequest->bRequest = KINGSUN_REQ_SEND;
751 kingsun->tx_setuprequest->wValue = 0;
752 kingsun->tx_setuprequest->wIndex = 0;
753 kingsun->tx_setuprequest->wLength = 0;
754
755
756 kingsun->speed_setuprequest =
757 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
758 if (!kingsun->speed_setuprequest)
759 goto free_mem;
760 kingsun->speed_setuprequest->bRequestType =
761 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
762 kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND;
763 kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200);
764 kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001);
765 kingsun->speed_setuprequest->wLength =
766 cpu_to_le16(sizeof(struct ks959_speedparams));
767
768 printk(KERN_INFO "KingSun KS-959 IRDA/USB found at address %d, "
769 "Vendor: %x, Product: %x\n",
770 dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
771 le16_to_cpu(dev->descriptor.idProduct));
772
773
774 irda_init_max_qos_capabilies(&kingsun->qos);
775
776
777
778
779
780 kingsun->qos.baud_rate.bits =
781 IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600;
782 kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
783 irda_qos_bits_to_value(&kingsun->qos);
784
785
786 net->netdev_ops = &ks959_ops;
787
788 ret = register_netdev(net);
789 if (ret != 0)
790 goto free_mem;
791
792 dev_info(&net->dev, "IrDA: Registered KingSun KS-959 device %s\n",
793 net->name);
794
795 usb_set_intfdata(intf, kingsun);
796
797
798
799
800
801
802
803
804
805 return 0;
806
807 free_mem:
808 kfree(kingsun->speed_setuprequest);
809 kfree(kingsun->tx_setuprequest);
810 kfree(kingsun->tx_buf_xored);
811 kfree(kingsun->tx_buf_clear);
812 kfree(kingsun->rx_setuprequest);
813 kfree(kingsun->rx_buf);
814 free_netdev(net);
815 err_out1:
816 return ret;
817}
818
819
820
821
822static void ks959_disconnect(struct usb_interface *intf)
823{
824 struct ks959_cb *kingsun = usb_get_intfdata(intf);
825
826 if (!kingsun)
827 return;
828
829 unregister_netdev(kingsun->netdev);
830
831
832 if (kingsun->speed_urb != NULL) {
833 usb_kill_urb(kingsun->speed_urb);
834 usb_free_urb(kingsun->speed_urb);
835 kingsun->speed_urb = NULL;
836 }
837 if (kingsun->tx_urb != NULL) {
838 usb_kill_urb(kingsun->tx_urb);
839 usb_free_urb(kingsun->tx_urb);
840 kingsun->tx_urb = NULL;
841 }
842 if (kingsun->rx_urb != NULL) {
843 usb_kill_urb(kingsun->rx_urb);
844 usb_free_urb(kingsun->rx_urb);
845 kingsun->rx_urb = NULL;
846 }
847
848 kfree(kingsun->speed_setuprequest);
849 kfree(kingsun->tx_setuprequest);
850 kfree(kingsun->tx_buf_xored);
851 kfree(kingsun->tx_buf_clear);
852 kfree(kingsun->rx_setuprequest);
853 kfree(kingsun->rx_buf);
854 free_netdev(kingsun->netdev);
855
856 usb_set_intfdata(intf, NULL);
857}
858
859#ifdef CONFIG_PM
860
861static int ks959_suspend(struct usb_interface *intf, pm_message_t message)
862{
863 struct ks959_cb *kingsun = usb_get_intfdata(intf);
864
865 netif_device_detach(kingsun->netdev);
866 if (kingsun->speed_urb != NULL)
867 usb_kill_urb(kingsun->speed_urb);
868 if (kingsun->tx_urb != NULL)
869 usb_kill_urb(kingsun->tx_urb);
870 if (kingsun->rx_urb != NULL)
871 usb_kill_urb(kingsun->rx_urb);
872 return 0;
873}
874
875
876static int ks959_resume(struct usb_interface *intf)
877{
878 struct ks959_cb *kingsun = usb_get_intfdata(intf);
879
880 if (kingsun->rx_urb != NULL) {
881
882 usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
883 }
884 netif_device_attach(kingsun->netdev);
885
886 return 0;
887}
888#endif
889
890
891
892
893static struct usb_driver irda_driver = {
894 .name = "ks959-sir",
895 .probe = ks959_probe,
896 .disconnect = ks959_disconnect,
897 .id_table = dongles,
898#ifdef CONFIG_PM
899 .suspend = ks959_suspend,
900 .resume = ks959_resume,
901#endif
902};
903
904
905
906
907static int __init ks959_init(void)
908{
909 return usb_register(&irda_driver);
910}
911
912module_init(ks959_init);
913
914
915
916
917static void __exit ks959_cleanup(void)
918{
919
920 usb_deregister(&irda_driver);
921}
922
923module_exit(ks959_cleanup);
924
925MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
926MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
927MODULE_LICENSE("GPL");
928