1 /*****************************************************************************
3 * Filename: ks959-sir.c
5 * Description: Irda KingSun KS-959 USB Dongle
7 * Author: Alex Villacís Lasso <a_villacis@palosanto.com>
8 * with help from Domen Puncer <domen@coderock.org>
10 * Based on stir4200, mcs7780, kingsun-sir drivers.
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.
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.
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.
25 *****************************************************************************/
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
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
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.
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
53 * wValue <length of valid data before padding, little endian>
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
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
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
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
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
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:
93 * unsigned int dataBits : 2; // 0 - 5 bits 3 - 8 bits
95 * unsigned int stopBits : 1;
96 * unsigned int parityEnable : 1;
97 * unsigned int parityType : 1;
99 * unsigned int reset : 1;
100 * unsigned char reserved[3]; // set to 0
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.
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/kref.h>
122 #include <linux/usb.h>
123 #include <linux/device.h>
124 #include <linux/crc32.h>
126 #include <asm/unaligned.h>
127 #include <asm/byteorder.h>
128 #include <asm/uaccess.h>
130 #include <net/irda/irda.h>
131 #include <net/irda/wrapper.h>
132 #include <net/irda/crc.h>
134 #define KS959_VENDOR_ID 0x07d0
135 #define KS959_PRODUCT_ID 0x4959
137 /* These are the currently known USB ids */
138 static struct usb_device_id dongles
[] = {
139 /* KingSun Co,Ltd IrDA/USB Bridge */
140 {USB_DEVICE(KS959_VENDOR_ID
, KS959_PRODUCT_ID
)},
144 MODULE_DEVICE_TABLE(usb
, dongles
);
146 #define KINGSUN_MTT 0x07
147 #define KINGSUN_REQ_RECV 0x01
148 #define KINGSUN_REQ_SEND 0x09
150 #define KINGSUN_RCV_FIFO_SIZE 2048 /* Max length we can receive */
151 #define KINGSUN_SND_FIFO_SIZE 2048 /* Max packet we can send */
152 #define KINGSUN_SND_PACKET_SIZE 256 /* Max packet dongle can handle */
154 struct ks959_speedparams
{
155 __le32 baudrate
; /* baud rate, little endian */
158 } __attribute__ ((packed
));
160 #define KS_DATA_5_BITS 0x00
161 #define KS_DATA_6_BITS 0x01
162 #define KS_DATA_7_BITS 0x02
163 #define KS_DATA_8_BITS 0x03
165 #define KS_STOP_BITS_1 0x00
166 #define KS_STOP_BITS_2 0x08
168 #define KS_PAR_DISABLE 0x00
169 #define KS_PAR_EVEN 0x10
170 #define KS_PAR_ODD 0x30
171 #define KS_RESET 0x80
174 struct usb_device
*usbdev
; /* init: probe_irda */
175 struct net_device
*netdev
; /* network layer */
176 struct irlap_cb
*irlap
; /* The link layer we are binded to */
180 struct usb_ctrlrequest
*tx_setuprequest
;
183 unsigned int tx_buf_clear_used
;
184 unsigned int tx_buf_clear_sent
;
187 struct usb_ctrlrequest
*rx_setuprequest
;
190 __u8 rx_variable_xormask
;
191 iobuff_t rx_unwrap_buff
;
192 struct timeval rx_time
;
194 struct usb_ctrlrequest
*speed_setuprequest
;
195 struct urb
*speed_urb
;
196 struct ks959_speedparams speedparams
;
197 unsigned int new_speed
;
203 /* Procedure to perform the obfuscation/padding expected by the dongle
205 * buf_cleartext (IN) Cleartext version of the IrDA frame to transmit
206 * len_cleartext (IN) Length of the cleartext version of IrDA frame
207 * buf_xoredtext (OUT) Obfuscated version of frame built by proc
208 * len_maxbuf (OUT) Maximum space available at buf_xoredtext
210 * (return) length of obfuscated frame with padding
212 * If not enough space (as indicated by len_maxbuf vs. required padding),
215 * The value of lookup_string is actually a required portion of the algorithm.
216 * Seems the designer of the dongle wanted to state who exactly is responsible
217 * for implementing obfuscation. Send your best (or other) wishes to him ]:-)
219 static unsigned int obfuscate_tx_buffer(const __u8
* buf_cleartext
,
220 unsigned int len_cleartext
,
221 __u8
* buf_xoredtext
,
222 unsigned int len_maxbuf
)
224 unsigned int len_xoredtext
;
226 /* Calculate required length with padding, check for necessary space */
227 len_xoredtext
= ((len_cleartext
+ 7) & ~0x7) + 0x10;
228 if (len_xoredtext
<= len_maxbuf
) {
229 static const __u8 lookup_string
[] = "wangshuofei19710";
232 /* Unlike the WinXP driver, we *do* clear out the padding */
233 memset(buf_xoredtext
, 0, len_xoredtext
);
235 xor_mask
= lookup_string
[(len_cleartext
& 0x0f) ^ 0x06] ^ 0x55;
237 while (len_cleartext
-- > 0) {
238 *buf_xoredtext
++ = *buf_cleartext
++ ^ xor_mask
;
243 return len_xoredtext
;
246 /* Callback transmission routine */
247 static void ks959_speed_irq(struct urb
*urb
)
249 /* unlink, shutdown, unplug, other nasties */
250 if (urb
->status
!= 0) {
251 err("ks959_speed_irq: urb asynchronously failed - %d",
256 /* Send a control request to change speed of the dongle */
257 static int ks959_change_speed(struct ks959_cb
*kingsun
, unsigned speed
)
259 static unsigned int supported_speeds
[] = { 2400, 9600, 19200, 38400,
260 57600, 115200, 576000, 1152000, 4000000, 0
265 if (kingsun
->speed_setuprequest
== NULL
|| kingsun
->speed_urb
== NULL
)
268 /* Check that requested speed is among the supported ones */
269 for (i
= 0; supported_speeds
[i
] && supported_speeds
[i
] != speed
; i
++) ;
270 if (supported_speeds
[i
] == 0)
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
;
277 /* speed_setuprequest pre-filled in ks959_probe */
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
,
284 kingsun
->speed_urb
->status
= 0;
285 err
= usb_submit_urb(kingsun
->speed_urb
, GFP_ATOMIC
);
290 /* Submit one fragment of an IrDA frame to the dongle */
291 static void ks959_send_irq(struct urb
*urb
);
292 static int ks959_submit_tx_fragment(struct ks959_cb
*kingsun
)
295 unsigned int wraplen
;
298 /* Check whether current plaintext can produce a padded buffer that fits
299 within the range handled by the dongle */
300 wraplen
= (KINGSUN_SND_PACKET_SIZE
& ~0x7) - 0x10;
301 if (wraplen
> kingsun
->tx_buf_clear_used
)
302 wraplen
= kingsun
->tx_buf_clear_used
;
304 /* Perform dongle obfuscation. Also remove the portion of the frame that
305 was just obfuscated and will now be sent to the dongle. */
306 padlen
= obfuscate_tx_buffer(kingsun
->tx_buf_clear
, wraplen
,
307 kingsun
->tx_buf_xored
,
308 KINGSUN_SND_PACKET_SIZE
);
310 /* Calculate how much data can be transmitted in this urb */
311 kingsun
->tx_setuprequest
->wValue
= cpu_to_le16(wraplen
);
312 kingsun
->tx_setuprequest
->wLength
= cpu_to_le16(padlen
);
313 /* Rest of the fields were filled in ks959_probe */
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
);
322 /* Remember how much data was sent, in order to update at callback */
323 kingsun
->tx_buf_clear_sent
= (ret
== 0) ? wraplen
: 0;
327 /* Callback transmission routine */
328 static void ks959_send_irq(struct urb
*urb
)
330 struct ks959_cb
*kingsun
= urb
->context
;
331 struct net_device
*netdev
= kingsun
->netdev
;
334 /* in process of stopping, just drop data */
335 if (!netif_running(kingsun
->netdev
)) {
336 err("ks959_send_irq: Network not running!");
340 /* unlink, shutdown, unplug, other nasties */
341 if (urb
->status
!= 0) {
342 err("ks959_send_irq: urb asynchronously failed - %d",
347 if (kingsun
->tx_buf_clear_used
> 0) {
348 /* Update data remaining to be sent */
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
);
356 kingsun
->tx_buf_clear_used
-= kingsun
->tx_buf_clear_sent
;
357 kingsun
->tx_buf_clear_sent
= 0;
359 if (kingsun
->tx_buf_clear_used
> 0) {
360 /* There is more data to be sent */
361 if ((ret
= ks959_submit_tx_fragment(kingsun
)) != 0) {
362 err("ks959_send_irq: failed tx_urb submit: %d",
369 netdev
->stats
.tx_errors
++;
370 netif_start_queue(netdev
);
374 /* All data sent, send next speed && wake network queue */
375 if (kingsun
->new_speed
!= -1 &&
376 cpu_to_le32(kingsun
->new_speed
) !=
377 kingsun
->speedparams
.baudrate
)
378 ks959_change_speed(kingsun
, kingsun
->new_speed
);
380 netif_wake_queue(netdev
);
386 * Called from net/core when new frame is available.
388 static netdev_tx_t
ks959_hard_xmit(struct sk_buff
*skb
,
389 struct net_device
*netdev
)
391 struct ks959_cb
*kingsun
;
392 unsigned int wraplen
;
395 netif_stop_queue(netdev
);
397 /* the IRDA wrapping routines don't deal with non linear skb */
398 SKB_LINEAR_ASSERT(skb
);
400 kingsun
= netdev_priv(netdev
);
402 spin_lock(&kingsun
->lock
);
403 kingsun
->new_speed
= irda_get_next_speed(skb
);
405 /* Append data to the end of whatever data remains to be transmitted */
407 async_wrap_skb(skb
, kingsun
->tx_buf_clear
, KINGSUN_SND_FIFO_SIZE
);
408 kingsun
->tx_buf_clear_used
= wraplen
;
410 if ((ret
= ks959_submit_tx_fragment(kingsun
)) != 0) {
411 err("ks959_hard_xmit: failed tx_urb submit: %d", ret
);
417 netdev
->stats
.tx_errors
++;
418 netif_start_queue(netdev
);
421 netdev
->stats
.tx_packets
++;
422 netdev
->stats
.tx_bytes
+= skb
->len
;
427 spin_unlock(&kingsun
->lock
);
432 /* Receive callback function */
433 static void ks959_rcv_irq(struct urb
*urb
)
435 struct ks959_cb
*kingsun
= urb
->context
;
438 /* in process of stopping, just drop data */
439 if (!netif_running(kingsun
->netdev
)) {
440 kingsun
->receiving
= 0;
444 /* unlink, shutdown, unplug, other nasties */
445 if (urb
->status
!= 0) {
446 err("kingsun_rcv_irq: urb asynchronously failed - %d",
448 kingsun
->receiving
= 0;
452 if (urb
->actual_length
> 0) {
453 __u8
*bytes
= urb
->transfer_buffer
;
456 for (i
= 0; i
< urb
->actual_length
; i
++) {
457 /* De-obfuscation implemented here: variable portion of
458 xormask is incremented, and then used with the encoded
459 byte for the XOR. The result of the operation is used
460 to unwrap the SIR frame. */
461 kingsun
->rx_variable_xormask
++;
463 bytes
[i
] ^ kingsun
->rx_variable_xormask
^ 0x55u
;
465 /* rx_variable_xormask doubles as an index counter so we
466 can skip the byte at 0xff (wrapped around to 0).
468 if (kingsun
->rx_variable_xormask
!= 0) {
469 async_unwrap_char(kingsun
->netdev
,
470 &kingsun
->netdev
->stats
,
471 &kingsun
->rx_unwrap_buff
,
475 do_gettimeofday(&kingsun
->rx_time
);
477 (kingsun
->rx_unwrap_buff
.state
!= OUTSIDE_FRAME
) ? 1 : 0;
480 /* This urb has already been filled in kingsun_net_open. Setup
481 packet must be re-filled, but it is assumed that urb keeps the
482 pointer to the initial setup packet, as well as the payload buffer.
483 Setup packet is already pre-filled at ks959_probe.
486 ret
= usb_submit_urb(urb
, GFP_ATOMIC
);
490 * Function kingsun_net_open (dev)
492 * Network device is taken up. Usually this is done by "ifconfig irda0 up"
494 static int ks959_net_open(struct net_device
*netdev
)
496 struct ks959_cb
*kingsun
= netdev_priv(netdev
);
500 /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
501 kingsun
->receiving
= 0;
503 /* Initialize for SIR to copy data directly into skb. */
504 kingsun
->rx_unwrap_buff
.in_frame
= FALSE
;
505 kingsun
->rx_unwrap_buff
.state
= OUTSIDE_FRAME
;
506 kingsun
->rx_unwrap_buff
.truesize
= IRDA_SKB_MAX_MTU
;
507 kingsun
->rx_unwrap_buff
.skb
= dev_alloc_skb(IRDA_SKB_MAX_MTU
);
508 if (!kingsun
->rx_unwrap_buff
.skb
)
511 skb_reserve(kingsun
->rx_unwrap_buff
.skb
, 1);
512 kingsun
->rx_unwrap_buff
.head
= kingsun
->rx_unwrap_buff
.skb
->data
;
513 do_gettimeofday(&kingsun
->rx_time
);
515 kingsun
->rx_urb
= usb_alloc_urb(0, GFP_KERNEL
);
516 if (!kingsun
->rx_urb
)
519 kingsun
->tx_urb
= usb_alloc_urb(0, GFP_KERNEL
);
520 if (!kingsun
->tx_urb
)
523 kingsun
->speed_urb
= usb_alloc_urb(0, GFP_KERNEL
);
524 if (!kingsun
->speed_urb
)
527 /* Initialize speed for dongle */
528 kingsun
->new_speed
= 9600;
529 err
= ks959_change_speed(kingsun
, 9600);
534 * Now that everything should be initialized properly,
535 * Open new IrLAP layer instance to take care of us...
537 sprintf(hwname
, "usb#%d", kingsun
->usbdev
->devnum
);
538 kingsun
->irlap
= irlap_open(netdev
, &kingsun
->qos
, hwname
);
539 if (!kingsun
->irlap
) {
540 err("ks959-sir: irlap_open failed");
544 /* Start reception. Setup request already pre-filled in ks959_probe */
545 usb_fill_control_urb(kingsun
->rx_urb
, kingsun
->usbdev
,
546 usb_rcvctrlpipe(kingsun
->usbdev
, 0),
547 (unsigned char *)kingsun
->rx_setuprequest
,
548 kingsun
->rx_buf
, KINGSUN_RCV_FIFO_SIZE
,
549 ks959_rcv_irq
, kingsun
);
550 kingsun
->rx_urb
->status
= 0;
551 err
= usb_submit_urb(kingsun
->rx_urb
, GFP_KERNEL
);
553 err("ks959-sir: first urb-submit failed: %d", err
);
557 netif_start_queue(netdev
);
559 /* Situation at this point:
560 - all work buffers allocated
561 - urbs allocated and ready to fill
562 - max rx packet known (in max_rx)
563 - unwrap state machine initialized, in state outside of any frame
564 - receive request in progress
565 - IrLAP layer started, about to hand over packets to send
571 irlap_close(kingsun
->irlap
);
573 usb_free_urb(kingsun
->speed_urb
);
574 kingsun
->speed_urb
= NULL
;
575 usb_free_urb(kingsun
->tx_urb
);
576 kingsun
->tx_urb
= NULL
;
577 usb_free_urb(kingsun
->rx_urb
);
578 kingsun
->rx_urb
= NULL
;
579 if (kingsun
->rx_unwrap_buff
.skb
) {
580 kfree_skb(kingsun
->rx_unwrap_buff
.skb
);
581 kingsun
->rx_unwrap_buff
.skb
= NULL
;
582 kingsun
->rx_unwrap_buff
.head
= NULL
;
588 * Function kingsun_net_close (kingsun)
590 * Network device is taken down. Usually this is done by
591 * "ifconfig irda0 down"
593 static int ks959_net_close(struct net_device
*netdev
)
595 struct ks959_cb
*kingsun
= netdev_priv(netdev
);
597 /* Stop transmit processing */
598 netif_stop_queue(netdev
);
600 /* Mop up receive && transmit urb's */
601 usb_kill_urb(kingsun
->tx_urb
);
602 usb_free_urb(kingsun
->tx_urb
);
603 kingsun
->tx_urb
= NULL
;
605 usb_kill_urb(kingsun
->speed_urb
);
606 usb_free_urb(kingsun
->speed_urb
);
607 kingsun
->speed_urb
= NULL
;
609 usb_kill_urb(kingsun
->rx_urb
);
610 usb_free_urb(kingsun
->rx_urb
);
611 kingsun
->rx_urb
= NULL
;
613 kfree_skb(kingsun
->rx_unwrap_buff
.skb
);
614 kingsun
->rx_unwrap_buff
.skb
= NULL
;
615 kingsun
->rx_unwrap_buff
.head
= NULL
;
616 kingsun
->rx_unwrap_buff
.in_frame
= FALSE
;
617 kingsun
->rx_unwrap_buff
.state
= OUTSIDE_FRAME
;
618 kingsun
->receiving
= 0;
620 /* Stop and remove instance of IrLAP */
622 irlap_close(kingsun
->irlap
);
624 kingsun
->irlap
= NULL
;
630 * IOCTLs : Extra out-of-band network commands...
632 static int ks959_net_ioctl(struct net_device
*netdev
, struct ifreq
*rq
, int cmd
)
634 struct if_irda_req
*irq
= (struct if_irda_req
*)rq
;
635 struct ks959_cb
*kingsun
= netdev_priv(netdev
);
639 case SIOCSBANDWIDTH
: /* Set bandwidth */
640 if (!capable(CAP_NET_ADMIN
))
643 /* Check if the device is still there */
644 if (netif_device_present(kingsun
->netdev
))
645 return ks959_change_speed(kingsun
, irq
->ifr_baudrate
);
648 case SIOCSMEDIABUSY
: /* Set media busy */
649 if (!capable(CAP_NET_ADMIN
))
652 /* Check if the IrDA stack is still there */
653 if (netif_running(kingsun
->netdev
))
654 irda_device_set_media_busy(kingsun
->netdev
, TRUE
);
658 /* Only approximately true */
659 irq
->ifr_receiving
= kingsun
->receiving
;
669 static const struct net_device_ops ks959_ops
= {
670 .ndo_start_xmit
= ks959_hard_xmit
,
671 .ndo_open
= ks959_net_open
,
672 .ndo_stop
= ks959_net_close
,
673 .ndo_do_ioctl
= ks959_net_ioctl
,
676 * This routine is called by the USB subsystem for each new device
677 * in the system. We need to check if the device is ours, and in
678 * this case start handling it.
680 static int ks959_probe(struct usb_interface
*intf
,
681 const struct usb_device_id
*id
)
683 struct usb_device
*dev
= interface_to_usbdev(intf
);
684 struct ks959_cb
*kingsun
= NULL
;
685 struct net_device
*net
= NULL
;
688 /* Allocate network device container. */
689 net
= alloc_irdadev(sizeof(*kingsun
));
693 SET_NETDEV_DEV(net
, &intf
->dev
);
694 kingsun
= netdev_priv(net
);
695 kingsun
->netdev
= net
;
696 kingsun
->usbdev
= dev
;
697 kingsun
->irlap
= NULL
;
698 kingsun
->tx_setuprequest
= NULL
;
699 kingsun
->tx_urb
= NULL
;
700 kingsun
->tx_buf_clear
= NULL
;
701 kingsun
->tx_buf_xored
= NULL
;
702 kingsun
->tx_buf_clear_used
= 0;
703 kingsun
->tx_buf_clear_sent
= 0;
705 kingsun
->rx_setuprequest
= NULL
;
706 kingsun
->rx_urb
= NULL
;
707 kingsun
->rx_buf
= NULL
;
708 kingsun
->rx_variable_xormask
= 0;
709 kingsun
->rx_unwrap_buff
.in_frame
= FALSE
;
710 kingsun
->rx_unwrap_buff
.state
= OUTSIDE_FRAME
;
711 kingsun
->rx_unwrap_buff
.skb
= NULL
;
712 kingsun
->receiving
= 0;
713 spin_lock_init(&kingsun
->lock
);
715 kingsun
->speed_setuprequest
= NULL
;
716 kingsun
->speed_urb
= NULL
;
717 kingsun
->speedparams
.baudrate
= 0;
719 /* Allocate input buffer */
720 kingsun
->rx_buf
= kmalloc(KINGSUN_RCV_FIFO_SIZE
, GFP_KERNEL
);
721 if (!kingsun
->rx_buf
)
724 /* Allocate input setup packet */
725 kingsun
->rx_setuprequest
=
726 kmalloc(sizeof(struct usb_ctrlrequest
), GFP_KERNEL
);
727 if (!kingsun
->rx_setuprequest
)
729 kingsun
->rx_setuprequest
->bRequestType
=
730 USB_DIR_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
;
731 kingsun
->rx_setuprequest
->bRequest
= KINGSUN_REQ_RECV
;
732 kingsun
->rx_setuprequest
->wValue
= cpu_to_le16(0x0200);
733 kingsun
->rx_setuprequest
->wIndex
= 0;
734 kingsun
->rx_setuprequest
->wLength
= cpu_to_le16(KINGSUN_RCV_FIFO_SIZE
);
736 /* Allocate output buffer */
737 kingsun
->tx_buf_clear
= kmalloc(KINGSUN_SND_FIFO_SIZE
, GFP_KERNEL
);
738 if (!kingsun
->tx_buf_clear
)
740 kingsun
->tx_buf_xored
= kmalloc(KINGSUN_SND_PACKET_SIZE
, GFP_KERNEL
);
741 if (!kingsun
->tx_buf_xored
)
744 /* Allocate and initialize output setup packet */
745 kingsun
->tx_setuprequest
=
746 kmalloc(sizeof(struct usb_ctrlrequest
), GFP_KERNEL
);
747 if (!kingsun
->tx_setuprequest
)
749 kingsun
->tx_setuprequest
->bRequestType
=
750 USB_DIR_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
;
751 kingsun
->tx_setuprequest
->bRequest
= KINGSUN_REQ_SEND
;
752 kingsun
->tx_setuprequest
->wValue
= 0;
753 kingsun
->tx_setuprequest
->wIndex
= 0;
754 kingsun
->tx_setuprequest
->wLength
= 0;
756 /* Allocate and initialize speed setup packet */
757 kingsun
->speed_setuprequest
=
758 kmalloc(sizeof(struct usb_ctrlrequest
), GFP_KERNEL
);
759 if (!kingsun
->speed_setuprequest
)
761 kingsun
->speed_setuprequest
->bRequestType
=
762 USB_DIR_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
;
763 kingsun
->speed_setuprequest
->bRequest
= KINGSUN_REQ_SEND
;
764 kingsun
->speed_setuprequest
->wValue
= cpu_to_le16(0x0200);
765 kingsun
->speed_setuprequest
->wIndex
= cpu_to_le16(0x0001);
766 kingsun
->speed_setuprequest
->wLength
=
767 cpu_to_le16(sizeof(struct ks959_speedparams
));
769 printk(KERN_INFO
"KingSun KS-959 IRDA/USB found at address %d, "
770 "Vendor: %x, Product: %x\n",
771 dev
->devnum
, le16_to_cpu(dev
->descriptor
.idVendor
),
772 le16_to_cpu(dev
->descriptor
.idProduct
));
774 /* Initialize QoS for this device */
775 irda_init_max_qos_capabilies(&kingsun
->qos
);
777 /* Baud rates known to be supported. Please uncomment if devices (other
778 than a SonyEriccson K300 phone) can be shown to support higher speed
781 kingsun
->qos
.baud_rate
.bits
=
782 IR_2400
| IR_9600
| IR_19200
| IR_38400
| IR_57600
;
783 kingsun
->qos
.min_turn_time
.bits
&= KINGSUN_MTT
;
784 irda_qos_bits_to_value(&kingsun
->qos
);
786 /* Override the network functions we need to use */
787 net
->netdev_ops
= &ks959_ops
;
789 ret
= register_netdev(net
);
793 dev_info(&net
->dev
, "IrDA: Registered KingSun KS-959 device %s\n",
796 usb_set_intfdata(intf
, kingsun
);
798 /* Situation at this point:
799 - all work buffers allocated
800 - setup requests pre-filled
801 - urbs not allocated, set to NULL
802 - max rx packet known (is KINGSUN_FIFO_SIZE)
803 - unwrap state machine (partially) initialized, but skb == NULL
809 kfree(kingsun
->speed_setuprequest
);
810 kfree(kingsun
->tx_setuprequest
);
811 kfree(kingsun
->tx_buf_xored
);
812 kfree(kingsun
->tx_buf_clear
);
813 kfree(kingsun
->rx_setuprequest
);
814 kfree(kingsun
->rx_buf
);
821 * The current device is removed, the USB layer tell us to shut it down...
823 static void ks959_disconnect(struct usb_interface
*intf
)
825 struct ks959_cb
*kingsun
= usb_get_intfdata(intf
);
830 unregister_netdev(kingsun
->netdev
);
832 /* Mop up receive && transmit urb's */
833 if (kingsun
->speed_urb
!= NULL
) {
834 usb_kill_urb(kingsun
->speed_urb
);
835 usb_free_urb(kingsun
->speed_urb
);
836 kingsun
->speed_urb
= NULL
;
838 if (kingsun
->tx_urb
!= NULL
) {
839 usb_kill_urb(kingsun
->tx_urb
);
840 usb_free_urb(kingsun
->tx_urb
);
841 kingsun
->tx_urb
= NULL
;
843 if (kingsun
->rx_urb
!= NULL
) {
844 usb_kill_urb(kingsun
->rx_urb
);
845 usb_free_urb(kingsun
->rx_urb
);
846 kingsun
->rx_urb
= NULL
;
849 kfree(kingsun
->speed_setuprequest
);
850 kfree(kingsun
->tx_setuprequest
);
851 kfree(kingsun
->tx_buf_xored
);
852 kfree(kingsun
->tx_buf_clear
);
853 kfree(kingsun
->rx_setuprequest
);
854 kfree(kingsun
->rx_buf
);
855 free_netdev(kingsun
->netdev
);
857 usb_set_intfdata(intf
, NULL
);
861 /* USB suspend, so power off the transmitter/receiver */
862 static int ks959_suspend(struct usb_interface
*intf
, pm_message_t message
)
864 struct ks959_cb
*kingsun
= usb_get_intfdata(intf
);
866 netif_device_detach(kingsun
->netdev
);
867 if (kingsun
->speed_urb
!= NULL
)
868 usb_kill_urb(kingsun
->speed_urb
);
869 if (kingsun
->tx_urb
!= NULL
)
870 usb_kill_urb(kingsun
->tx_urb
);
871 if (kingsun
->rx_urb
!= NULL
)
872 usb_kill_urb(kingsun
->rx_urb
);
876 /* Coming out of suspend, so reset hardware */
877 static int ks959_resume(struct usb_interface
*intf
)
879 struct ks959_cb
*kingsun
= usb_get_intfdata(intf
);
881 if (kingsun
->rx_urb
!= NULL
) {
882 /* Setup request already filled in ks959_probe */
883 usb_submit_urb(kingsun
->rx_urb
, GFP_KERNEL
);
885 netif_device_attach(kingsun
->netdev
);
892 * USB device callbacks
894 static struct usb_driver irda_driver
= {
896 .probe
= ks959_probe
,
897 .disconnect
= ks959_disconnect
,
900 .suspend
= ks959_suspend
,
901 .resume
= ks959_resume
,
908 static int __init
ks959_init(void)
910 return usb_register(&irda_driver
);
913 module_init(ks959_init
);
918 static void __exit
ks959_cleanup(void)
920 /* Deregister the driver and remove all pending instances */
921 usb_deregister(&irda_driver
);
924 module_exit(ks959_cleanup
);
926 MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
927 MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
928 MODULE_LICENSE("GPL");