• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*****************************************************************************
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/kref.h>
122 #include <linux/usb.h>
123 #include <linux/device.h>
124 #include <linux/crc32.h>
125 
126 #include <asm/unaligned.h>
127 #include <asm/byteorder.h>
128 #include <asm/uaccess.h>
129 
130 #include <net/irda/irda.h>
131 #include <net/irda/wrapper.h>
132 #include <net/irda/crc.h>
133 
134 #define KS959_VENDOR_ID 0x07d0
135 #define KS959_PRODUCT_ID 0x4959
136 
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)},
141 	{}
142 };
143 
144 MODULE_DEVICE_TABLE(usb, dongles);
145 
146 #define KINGSUN_MTT 0x07
147 #define KINGSUN_REQ_RECV 0x01
148 #define KINGSUN_REQ_SEND 0x09
149 
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 */
153 
154 struct ks959_speedparams {
155 	__le32 baudrate;	/* baud rate, little endian */
156 	__u8 flags;
157 	__u8 reserved[3];
158 } __attribute__ ((packed));
159 
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
164 
165 #define KS_STOP_BITS_1 0x00
166 #define KS_STOP_BITS_2 0x08
167 
168 #define KS_PAR_DISABLE    0x00
169 #define KS_PAR_EVEN    0x10
170 #define KS_PAR_ODD    0x30
171 #define KS_RESET    0x80
172 
173 struct ks959_cb {
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 */
177 
178 	struct qos_info qos;
179 
180 	struct usb_ctrlrequest *tx_setuprequest;
181 	struct urb *tx_urb;
182 	__u8 *tx_buf_clear;
183 	unsigned int tx_buf_clear_used;
184 	unsigned int tx_buf_clear_sent;
185 	__u8 *tx_buf_xored;
186 
187 	struct usb_ctrlrequest *rx_setuprequest;
188 	struct urb *rx_urb;
189 	__u8 *rx_buf;
190 	__u8 rx_variable_xormask;
191 	iobuff_t rx_unwrap_buff;
192 	struct timeval rx_time;
193 
194 	struct usb_ctrlrequest *speed_setuprequest;
195 	struct urb *speed_urb;
196 	struct ks959_speedparams speedparams;
197 	unsigned int new_speed;
198 
199 	spinlock_t lock;
200 	int receiving;
201 };
202 
203 /* Procedure to perform the obfuscation/padding expected by the dongle
204  *
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
209  *
210  * (return)         length of obfuscated frame with padding
211  *
212  * If not enough space (as indicated by len_maxbuf vs. required padding),
213  * zero is returned
214  *
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 ]:-)
218  */
obfuscate_tx_buffer(const __u8 * buf_cleartext,unsigned int len_cleartext,__u8 * buf_xoredtext,unsigned int len_maxbuf)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)
223 {
224 	unsigned int len_xoredtext;
225 
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";
230 		__u8 xor_mask;
231 
232 		/* Unlike the WinXP driver, we *do* clear out the padding */
233 		memset(buf_xoredtext, 0, len_xoredtext);
234 
235 		xor_mask = lookup_string[(len_cleartext & 0x0f) ^ 0x06] ^ 0x55;
236 
237 		while (len_cleartext-- > 0) {
238 			*buf_xoredtext++ = *buf_cleartext++ ^ xor_mask;
239 		}
240 	} else {
241 		len_xoredtext = 0;
242 	}
243 	return len_xoredtext;
244 }
245 
246 /* Callback transmission routine */
ks959_speed_irq(struct urb * urb)247 static void ks959_speed_irq(struct urb *urb)
248 {
249 	/* unlink, shutdown, unplug, other nasties */
250 	if (urb->status != 0) {
251 		err("ks959_speed_irq: urb asynchronously failed - %d",
252 		    urb->status);
253 	}
254 }
255 
256 /* Send a control request to change speed of the dongle */
ks959_change_speed(struct ks959_cb * kingsun,unsigned speed)257 static 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 	/* 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)
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 	/* 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,
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 /* Submit one fragment of an IrDA frame to the dongle */
291 static void ks959_send_irq(struct urb *urb);
ks959_submit_tx_fragment(struct ks959_cb * kingsun)292 static int ks959_submit_tx_fragment(struct ks959_cb *kingsun)
293 {
294 	unsigned int padlen;
295 	unsigned int wraplen;
296 	int ret;
297 
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;
303 
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);
309 
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);
321 
322 	/* Remember how much data was sent, in order to update at callback */
323 	kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0;
324 	return ret;
325 }
326 
327 /* Callback transmission routine */
ks959_send_irq(struct urb * urb)328 static 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 	/* in process of stopping, just drop data */
335 	if (!netif_running(kingsun->netdev)) {
336 		err("ks959_send_irq: Network not running!");
337 		return;
338 	}
339 
340 	/* unlink, shutdown, unplug, other nasties */
341 	if (urb->status != 0) {
342 		err("ks959_send_irq: urb asynchronously failed - %d",
343 		    urb->status);
344 		return;
345 	}
346 
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);
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 			/* 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",
363 				    ret);
364 				switch (ret) {
365 				case -ENODEV:
366 				case -EPIPE:
367 					break;
368 				default:
369 					netdev->stats.tx_errors++;
370 					netif_start_queue(netdev);
371 				}
372 			}
373 		} else {
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);
379 
380 			netif_wake_queue(netdev);
381 		}
382 	}
383 }
384 
385 /*
386  * Called from net/core when new frame is available.
387  */
ks959_hard_xmit(struct sk_buff * skb,struct net_device * netdev)388 static int ks959_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
389 {
390 	struct ks959_cb *kingsun;
391 	unsigned int wraplen;
392 	int ret = 0;
393 
394 	if (skb == NULL || netdev == NULL)
395 		return -EINVAL;
396 
397 	netif_stop_queue(netdev);
398 
399 	/* the IRDA wrapping routines don't deal with non linear skb */
400 	SKB_LINEAR_ASSERT(skb);
401 
402 	kingsun = netdev_priv(netdev);
403 
404 	spin_lock(&kingsun->lock);
405 	kingsun->new_speed = irda_get_next_speed(skb);
406 
407 	/* Append data to the end of whatever data remains to be transmitted */
408 	wraplen =
409 	    async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE);
410 	kingsun->tx_buf_clear_used = wraplen;
411 
412 	if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
413 		err("ks959_hard_xmit: failed tx_urb submit: %d", 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 ret;
432 }
433 
434 /* Receive callback function */
ks959_rcv_irq(struct urb * urb)435 static void ks959_rcv_irq(struct urb *urb)
436 {
437 	struct ks959_cb *kingsun = urb->context;
438 	int ret;
439 
440 	/* in process of stopping, just drop data */
441 	if (!netif_running(kingsun->netdev)) {
442 		kingsun->receiving = 0;
443 		return;
444 	}
445 
446 	/* unlink, shutdown, unplug, other nasties */
447 	if (urb->status != 0) {
448 		err("kingsun_rcv_irq: urb asynchronously failed - %d",
449 		    urb->status);
450 		kingsun->receiving = 0;
451 		return;
452 	}
453 
454 	if (urb->actual_length > 0) {
455 		__u8 *bytes = urb->transfer_buffer;
456 		unsigned int i;
457 
458 		for (i = 0; i < urb->actual_length; i++) {
459 			/* De-obfuscation implemented here: variable portion of
460 			   xormask is incremented, and then used with the encoded
461 			   byte for the XOR. The result of the operation is used
462 			   to unwrap the SIR frame. */
463 			kingsun->rx_variable_xormask++;
464 			bytes[i] =
465 			    bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u;
466 
467 			/* rx_variable_xormask doubles as an index counter so we
468 			   can skip the byte at 0xff (wrapped around to 0).
469 			 */
470 			if (kingsun->rx_variable_xormask != 0) {
471 				async_unwrap_char(kingsun->netdev,
472 						  &kingsun->netdev->stats,
473 						  &kingsun->rx_unwrap_buff,
474 						  bytes[i]);
475 			}
476 		}
477 		do_gettimeofday(&kingsun->rx_time);
478 		kingsun->receiving =
479 		    (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
480 	}
481 
482 	/* This urb has already been filled in kingsun_net_open. Setup
483 	   packet must be re-filled, but it is assumed that urb keeps the
484 	   pointer to the initial setup packet, as well as the payload buffer.
485 	   Setup packet is already pre-filled at ks959_probe.
486 	 */
487 	urb->status = 0;
488 	ret = usb_submit_urb(urb, GFP_ATOMIC);
489 }
490 
491 /*
492  * Function kingsun_net_open (dev)
493  *
494  *    Network device is taken up. Usually this is done by "ifconfig irda0 up"
495  */
ks959_net_open(struct net_device * netdev)496 static 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 	/* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
503 	kingsun->receiving = 0;
504 
505 	/* Initialize for SIR to copy data directly into skb.  */
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 	do_gettimeofday(&kingsun->rx_time);
516 
517 	kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
518 	if (!kingsun->rx_urb)
519 		goto free_mem;
520 
521 	kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
522 	if (!kingsun->tx_urb)
523 		goto free_mem;
524 
525 	kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL);
526 	if (!kingsun->speed_urb)
527 		goto free_mem;
528 
529 	/* Initialize speed for dongle */
530 	kingsun->new_speed = 9600;
531 	err = ks959_change_speed(kingsun, 9600);
532 	if (err < 0)
533 		goto free_mem;
534 
535 	/*
536 	 * Now that everything should be initialized properly,
537 	 * Open new IrLAP layer instance to take care of us...
538 	 */
539 	sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
540 	kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
541 	if (!kingsun->irlap) {
542 		err("ks959-sir: irlap_open failed");
543 		goto free_mem;
544 	}
545 
546 	/* Start reception. Setup request already pre-filled in ks959_probe */
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 		err("ks959-sir: first urb-submit failed: %d", err);
556 		goto close_irlap;
557 	}
558 
559 	netif_start_queue(netdev);
560 
561 	/* Situation at this point:
562 	   - all work buffers allocated
563 	   - urbs allocated and ready to fill
564 	   - max rx packet known (in max_rx)
565 	   - unwrap state machine initialized, in state outside of any frame
566 	   - receive request in progress
567 	   - IrLAP layer started, about to hand over packets to send
568 	 */
569 
570 	return 0;
571 
572       close_irlap:
573 	irlap_close(kingsun->irlap);
574       free_mem:
575 	usb_free_urb(kingsun->speed_urb);
576 	kingsun->speed_urb = NULL;
577 	usb_free_urb(kingsun->tx_urb);
578 	kingsun->tx_urb = NULL;
579 	usb_free_urb(kingsun->rx_urb);
580 	kingsun->rx_urb = NULL;
581 	if (kingsun->rx_unwrap_buff.skb) {
582 		kfree_skb(kingsun->rx_unwrap_buff.skb);
583 		kingsun->rx_unwrap_buff.skb = NULL;
584 		kingsun->rx_unwrap_buff.head = NULL;
585 	}
586 	return err;
587 }
588 
589 /*
590  * Function kingsun_net_close (kingsun)
591  *
592  *    Network device is taken down. Usually this is done by
593  *    "ifconfig irda0 down"
594  */
ks959_net_close(struct net_device * netdev)595 static int ks959_net_close(struct net_device *netdev)
596 {
597 	struct ks959_cb *kingsun = netdev_priv(netdev);
598 
599 	/* Stop transmit processing */
600 	netif_stop_queue(netdev);
601 
602 	/* Mop up receive && transmit urb's */
603 	usb_kill_urb(kingsun->tx_urb);
604 	usb_free_urb(kingsun->tx_urb);
605 	kingsun->tx_urb = NULL;
606 
607 	usb_kill_urb(kingsun->speed_urb);
608 	usb_free_urb(kingsun->speed_urb);
609 	kingsun->speed_urb = NULL;
610 
611 	usb_kill_urb(kingsun->rx_urb);
612 	usb_free_urb(kingsun->rx_urb);
613 	kingsun->rx_urb = NULL;
614 
615 	kfree_skb(kingsun->rx_unwrap_buff.skb);
616 	kingsun->rx_unwrap_buff.skb = NULL;
617 	kingsun->rx_unwrap_buff.head = NULL;
618 	kingsun->rx_unwrap_buff.in_frame = FALSE;
619 	kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
620 	kingsun->receiving = 0;
621 
622 	/* Stop and remove instance of IrLAP */
623 	if (kingsun->irlap)
624 		irlap_close(kingsun->irlap);
625 
626 	kingsun->irlap = NULL;
627 
628 	return 0;
629 }
630 
631 /*
632  * IOCTLs : Extra out-of-band network commands...
633  */
ks959_net_ioctl(struct net_device * netdev,struct ifreq * rq,int cmd)634 static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
635 {
636 	struct if_irda_req *irq = (struct if_irda_req *)rq;
637 	struct ks959_cb *kingsun = netdev_priv(netdev);
638 	int ret = 0;
639 
640 	switch (cmd) {
641 	case SIOCSBANDWIDTH:	/* Set bandwidth */
642 		if (!capable(CAP_NET_ADMIN))
643 			return -EPERM;
644 
645 		/* Check if the device is still there */
646 		if (netif_device_present(kingsun->netdev))
647 			return ks959_change_speed(kingsun, irq->ifr_baudrate);
648 		break;
649 
650 	case SIOCSMEDIABUSY:	/* Set media busy */
651 		if (!capable(CAP_NET_ADMIN))
652 			return -EPERM;
653 
654 		/* Check if the IrDA stack is still there */
655 		if (netif_running(kingsun->netdev))
656 			irda_device_set_media_busy(kingsun->netdev, TRUE);
657 		break;
658 
659 	case SIOCGRECEIVING:
660 		/* Only approximately true */
661 		irq->ifr_receiving = kingsun->receiving;
662 		break;
663 
664 	default:
665 		ret = -EOPNOTSUPP;
666 	}
667 
668 	return ret;
669 }
670 
671 /*
672  * This routine is called by the USB subsystem for each new device
673  * in the system. We need to check if the device is ours, and in
674  * this case start handling it.
675  */
ks959_probe(struct usb_interface * intf,const struct usb_device_id * id)676 static int ks959_probe(struct usb_interface *intf,
677 		       const struct usb_device_id *id)
678 {
679 	struct usb_device *dev = interface_to_usbdev(intf);
680 	struct ks959_cb *kingsun = NULL;
681 	struct net_device *net = NULL;
682 	int ret = -ENOMEM;
683 
684 	/* Allocate network device container. */
685 	net = alloc_irdadev(sizeof(*kingsun));
686 	if (!net)
687 		goto err_out1;
688 
689 	SET_NETDEV_DEV(net, &intf->dev);
690 	kingsun = netdev_priv(net);
691 	kingsun->netdev = net;
692 	kingsun->usbdev = dev;
693 	kingsun->irlap = NULL;
694 	kingsun->tx_setuprequest = NULL;
695 	kingsun->tx_urb = NULL;
696 	kingsun->tx_buf_clear = NULL;
697 	kingsun->tx_buf_xored = NULL;
698 	kingsun->tx_buf_clear_used = 0;
699 	kingsun->tx_buf_clear_sent = 0;
700 
701 	kingsun->rx_setuprequest = NULL;
702 	kingsun->rx_urb = NULL;
703 	kingsun->rx_buf = NULL;
704 	kingsun->rx_variable_xormask = 0;
705 	kingsun->rx_unwrap_buff.in_frame = FALSE;
706 	kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
707 	kingsun->rx_unwrap_buff.skb = NULL;
708 	kingsun->receiving = 0;
709 	spin_lock_init(&kingsun->lock);
710 
711 	kingsun->speed_setuprequest = NULL;
712 	kingsun->speed_urb = NULL;
713 	kingsun->speedparams.baudrate = 0;
714 
715 	/* Allocate input buffer */
716 	kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL);
717 	if (!kingsun->rx_buf)
718 		goto free_mem;
719 
720 	/* Allocate input setup packet */
721 	kingsun->rx_setuprequest =
722 	    kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
723 	if (!kingsun->rx_setuprequest)
724 		goto free_mem;
725 	kingsun->rx_setuprequest->bRequestType =
726 	    USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
727 	kingsun->rx_setuprequest->bRequest = KINGSUN_REQ_RECV;
728 	kingsun->rx_setuprequest->wValue = cpu_to_le16(0x0200);
729 	kingsun->rx_setuprequest->wIndex = 0;
730 	kingsun->rx_setuprequest->wLength = cpu_to_le16(KINGSUN_RCV_FIFO_SIZE);
731 
732 	/* Allocate output buffer */
733 	kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL);
734 	if (!kingsun->tx_buf_clear)
735 		goto free_mem;
736 	kingsun->tx_buf_xored = kmalloc(KINGSUN_SND_PACKET_SIZE, GFP_KERNEL);
737 	if (!kingsun->tx_buf_xored)
738 		goto free_mem;
739 
740 	/* Allocate and initialize output setup packet */
741 	kingsun->tx_setuprequest =
742 	    kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
743 	if (!kingsun->tx_setuprequest)
744 		goto free_mem;
745 	kingsun->tx_setuprequest->bRequestType =
746 	    USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
747 	kingsun->tx_setuprequest->bRequest = KINGSUN_REQ_SEND;
748 	kingsun->tx_setuprequest->wValue = 0;
749 	kingsun->tx_setuprequest->wIndex = 0;
750 	kingsun->tx_setuprequest->wLength = 0;
751 
752 	/* Allocate and initialize speed setup packet */
753 	kingsun->speed_setuprequest =
754 	    kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
755 	if (!kingsun->speed_setuprequest)
756 		goto free_mem;
757 	kingsun->speed_setuprequest->bRequestType =
758 	    USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
759 	kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND;
760 	kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200);
761 	kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001);
762 	kingsun->speed_setuprequest->wLength =
763 	    cpu_to_le16(sizeof(struct ks959_speedparams));
764 
765 	printk(KERN_INFO "KingSun KS-959 IRDA/USB found at address %d, "
766 	       "Vendor: %x, Product: %x\n",
767 	       dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
768 	       le16_to_cpu(dev->descriptor.idProduct));
769 
770 	/* Initialize QoS for this device */
771 	irda_init_max_qos_capabilies(&kingsun->qos);
772 
773 	/* Baud rates known to be supported. Please uncomment if devices (other
774 	   than a SonyEriccson K300 phone) can be shown to support higher speed
775 	   with this dongle.
776 	 */
777 	kingsun->qos.baud_rate.bits =
778 	    IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600;
779 	kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
780 	irda_qos_bits_to_value(&kingsun->qos);
781 
782 	/* Override the network functions we need to use */
783 	net->hard_start_xmit = ks959_hard_xmit;
784 	net->open = ks959_net_open;
785 	net->stop = ks959_net_close;
786 	net->do_ioctl = ks959_net_ioctl;
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 	/* Situation at this point:
798 	   - all work buffers allocated
799 	   - setup requests pre-filled
800 	   - urbs not allocated, set to NULL
801 	   - max rx packet known (is KINGSUN_FIFO_SIZE)
802 	   - unwrap state machine (partially) initialized, but skb == NULL
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  * The current device is removed, the USB layer tell us to shut it down...
821  */
ks959_disconnect(struct usb_interface * intf)822 static 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 	/* Mop up receive && transmit urb's */
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 /* USB suspend, so power off the transmitter/receiver */
ks959_suspend(struct usb_interface * intf,pm_message_t message)861 static 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 /* Coming out of suspend, so reset hardware */
ks959_resume(struct usb_interface * intf)876 static 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 		/* Setup request already filled in ks959_probe */
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  * USB device callbacks
892  */
893 static 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  * Module insertion
906  */
ks959_init(void)907 static int __init ks959_init(void)
908 {
909 	return usb_register(&irda_driver);
910 }
911 
912 module_init(ks959_init);
913 
914 /*
915  * Module removal
916  */
ks959_cleanup(void)917 static void __exit ks959_cleanup(void)
918 {
919 	/* Deregister the driver and remove all pending instances */
920 	usb_deregister(&irda_driver);
921 }
922 
923 module_exit(ks959_cleanup);
924 
925 MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
926 MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
927 MODULE_LICENSE("GPL");
928