Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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/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/* These are the currently known USB ids */
137static struct usb_device_id dongles[] = {
138	/* KingSun Co,Ltd  IrDA/USB Bridge */
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	/* Max length we can receive */
150#define KINGSUN_SND_FIFO_SIZE    2048	/* Max packet we can send */
151#define KINGSUN_SND_PACKET_SIZE    256	/* Max packet dongle can handle */
152
153struct ks959_speedparams {
154	__le32 baudrate;	/* baud rate, little endian */
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;	/* init: probe_irda */
174	struct net_device *netdev;	/* network layer */
175	struct irlap_cb *irlap;	/* The link layer we are binded to */
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/* Procedure to perform the obfuscation/padding expected by the dongle
203 *
204 * buf_cleartext    (IN) Cleartext version of the IrDA frame to transmit
205 * len_cleartext    (IN) Length of the cleartext version of IrDA frame
206 * buf_xoredtext    (OUT) Obfuscated version of frame built by proc
207 * len_maxbuf        (OUT) Maximum space available at buf_xoredtext
208 *
209 * (return)         length of obfuscated frame with padding
210 *
211 * If not enough space (as indicated by len_maxbuf vs. required padding),
212 * zero is returned
213 *
214 * The value of lookup_string is actually a required portion of the algorithm.
215 * Seems the designer of the dongle wanted to state who exactly is responsible
216 * for implementing obfuscation. Send your best (or other) wishes to him ]:-)
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	/* Calculate required length with padding, check for necessary space */
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		/* Unlike the WinXP driver, we *do* clear out the padding */
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/* Callback transmission routine */
246static void ks959_speed_irq(struct urb *urb)
247{
248	/* unlink, shutdown, unplug, other nasties */
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/* Send a control request to change speed of the dongle */
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	/* 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 */
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	/* 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 */
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	/* in process of stopping, just drop data */
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	/* unlink, shutdown, unplug, other nasties */
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		/* Update data remaining to be sent */
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			/* There is more data to be sent */
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			/* All data sent, send next speed && wake network queue */
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 * Called from net/core when new frame is available.
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	/* the IRDA wrapping routines don't deal with non linear skb */
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	/* Append data to the end of whatever data remains to be transmitted */
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/* Receive callback function */
437static void ks959_rcv_irq(struct urb *urb)
438{
439	struct ks959_cb *kingsun = urb->context;
440	int ret;
441
442	/* in process of stopping, just drop data */
443	if (!netif_running(kingsun->netdev)) {
444		kingsun->receiving = 0;
445		return;
446	}
447
448	/* unlink, shutdown, unplug, other nasties */
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			/* De-obfuscation implemented here: variable portion of
463			   xormask is incremented, and then used with the encoded
464			   byte for the XOR. The result of the operation is used
465			   to unwrap the SIR frame. */
466			kingsun->rx_variable_xormask++;
467			bytes[i] =
468			    bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u;
469
470			/* rx_variable_xormask doubles as an index counter so we
471			   can skip the byte at 0xff (wrapped around to 0).
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	/* This urb has already been filled in kingsun_net_open. Setup
486	   packet must be re-filled, but it is assumed that urb keeps the
487	   pointer to the initial setup packet, as well as the payload buffer.
488	   Setup packet is already pre-filled at ks959_probe.
489	 */
490	urb->status = 0;
491	ret = usb_submit_urb(urb, GFP_ATOMIC);
492}
493
494/*
495 * Function kingsun_net_open (dev)
496 *
497 *    Network device is taken up. Usually this is done by "ifconfig irda0 up"
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	/* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
506	kingsun->receiving = 0;
507
508	/* Initialize for SIR to copy data directly into skb.  */
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	/* Initialize speed for dongle */
533	kingsun->new_speed = 9600;
534	err = ks959_change_speed(kingsun, 9600);
535	if (err < 0)
536		goto free_mem;
537
538	/*
539	 * Now that everything should be initialized properly,
540	 * Open new IrLAP layer instance to take care of us...
541	 */
542	sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
543	kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
544	if (!kingsun->irlap) {
545		dev_err(&kingsun->usbdev->dev, "irlap_open failed\n");
546		goto free_mem;
547	}
548
549	/* Start reception. Setup request already pre-filled in ks959_probe */
550	usb_fill_control_urb(kingsun->rx_urb, kingsun->usbdev,
551			     usb_rcvctrlpipe(kingsun->usbdev, 0),
552			     (unsigned char *)kingsun->rx_setuprequest,
553			     kingsun->rx_buf, KINGSUN_RCV_FIFO_SIZE,
554			     ks959_rcv_irq, kingsun);
555	kingsun->rx_urb->status = 0;
556	err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
557	if (err) {
558		dev_err(&kingsun->usbdev->dev,
559			"first urb-submit failed: %d\n", err);
560		goto close_irlap;
561	}
562
563	netif_start_queue(netdev);
564
565	/* Situation at this point:
566	   - all work buffers allocated
567	   - urbs allocated and ready to fill
568	   - max rx packet known (in max_rx)
569	   - unwrap state machine initialized, in state outside of any frame
570	   - receive request in progress
571	   - IrLAP layer started, about to hand over packets to send
572	 */
573
574	return 0;
575
576      close_irlap:
577	irlap_close(kingsun->irlap);
578      free_mem:
579	usb_free_urb(kingsun->speed_urb);
580	kingsun->speed_urb = NULL;
581	usb_free_urb(kingsun->tx_urb);
582	kingsun->tx_urb = NULL;
583	usb_free_urb(kingsun->rx_urb);
584	kingsun->rx_urb = NULL;
585	if (kingsun->rx_unwrap_buff.skb) {
586		kfree_skb(kingsun->rx_unwrap_buff.skb);
587		kingsun->rx_unwrap_buff.skb = NULL;
588		kingsun->rx_unwrap_buff.head = NULL;
589	}
590	return err;
591}
592
593/*
594 * Function kingsun_net_close (kingsun)
595 *
596 *    Network device is taken down. Usually this is done by
597 *    "ifconfig irda0 down"
598 */
599static int ks959_net_close(struct net_device *netdev)
600{
601	struct ks959_cb *kingsun = netdev_priv(netdev);
602
603	/* Stop transmit processing */
604	netif_stop_queue(netdev);
605
606	/* Mop up receive && transmit urb's */
607	usb_kill_urb(kingsun->tx_urb);
608	usb_free_urb(kingsun->tx_urb);
609	kingsun->tx_urb = NULL;
610
611	usb_kill_urb(kingsun->speed_urb);
612	usb_free_urb(kingsun->speed_urb);
613	kingsun->speed_urb = NULL;
614
615	usb_kill_urb(kingsun->rx_urb);
616	usb_free_urb(kingsun->rx_urb);
617	kingsun->rx_urb = NULL;
618
619	kfree_skb(kingsun->rx_unwrap_buff.skb);
620	kingsun->rx_unwrap_buff.skb = NULL;
621	kingsun->rx_unwrap_buff.head = NULL;
622	kingsun->rx_unwrap_buff.in_frame = FALSE;
623	kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
624	kingsun->receiving = 0;
625
626	/* Stop and remove instance of IrLAP */
627	if (kingsun->irlap)
628		irlap_close(kingsun->irlap);
629
630	kingsun->irlap = NULL;
631
632	return 0;
633}
634
635/*
636 * IOCTLs : Extra out-of-band network commands...
637 */
638static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
639{
640	struct if_irda_req *irq = (struct if_irda_req *)rq;
641	struct ks959_cb *kingsun = netdev_priv(netdev);
642	int ret = 0;
643
644	switch (cmd) {
645	case SIOCSBANDWIDTH:	/* Set bandwidth */
646		if (!capable(CAP_NET_ADMIN))
647			return -EPERM;
648
649		/* Check if the device is still there */
650		if (netif_device_present(kingsun->netdev))
651			return ks959_change_speed(kingsun, irq->ifr_baudrate);
652		break;
653
654	case SIOCSMEDIABUSY:	/* Set media busy */
655		if (!capable(CAP_NET_ADMIN))
656			return -EPERM;
657
658		/* Check if the IrDA stack is still there */
659		if (netif_running(kingsun->netdev))
660			irda_device_set_media_busy(kingsun->netdev, TRUE);
661		break;
662
663	case SIOCGRECEIVING:
664		/* Only approximately true */
665		irq->ifr_receiving = kingsun->receiving;
666		break;
667
668	default:
669		ret = -EOPNOTSUPP;
670	}
671
672	return ret;
673}
674
675static const struct net_device_ops ks959_ops = {
676	.ndo_start_xmit	= ks959_hard_xmit,
677	.ndo_open	= ks959_net_open,
678	.ndo_stop	= ks959_net_close,
679	.ndo_do_ioctl	= ks959_net_ioctl,
680};
681/*
682 * This routine is called by the USB subsystem for each new device
683 * in the system. We need to check if the device is ours, and in
684 * this case start handling it.
685 */
686static int ks959_probe(struct usb_interface *intf,
687		       const struct usb_device_id *id)
688{
689	struct usb_device *dev = interface_to_usbdev(intf);
690	struct ks959_cb *kingsun = NULL;
691	struct net_device *net = NULL;
692	int ret = -ENOMEM;
693
694	/* Allocate network device container. */
695	net = alloc_irdadev(sizeof(*kingsun));
696	if (!net)
697		goto err_out1;
698
699	SET_NETDEV_DEV(net, &intf->dev);
700	kingsun = netdev_priv(net);
701	kingsun->netdev = net;
702	kingsun->usbdev = dev;
703	kingsun->irlap = NULL;
704	kingsun->tx_setuprequest = NULL;
705	kingsun->tx_urb = NULL;
706	kingsun->tx_buf_clear = NULL;
707	kingsun->tx_buf_xored = NULL;
708	kingsun->tx_buf_clear_used = 0;
709	kingsun->tx_buf_clear_sent = 0;
710
711	kingsun->rx_setuprequest = NULL;
712	kingsun->rx_urb = NULL;
713	kingsun->rx_buf = NULL;
714	kingsun->rx_variable_xormask = 0;
715	kingsun->rx_unwrap_buff.in_frame = FALSE;
716	kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
717	kingsun->rx_unwrap_buff.skb = NULL;
718	kingsun->receiving = 0;
719	spin_lock_init(&kingsun->lock);
720
721	kingsun->speed_setuprequest = NULL;
722	kingsun->speed_urb = NULL;
723	kingsun->speedparams.baudrate = 0;
724
725	/* Allocate input buffer */
726	kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL);
727	if (!kingsun->rx_buf)
728		goto free_mem;
729
730	/* Allocate input setup packet */
731	kingsun->rx_setuprequest =
732	    kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
733	if (!kingsun->rx_setuprequest)
734		goto free_mem;
735	kingsun->rx_setuprequest->bRequestType =
736	    USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
737	kingsun->rx_setuprequest->bRequest = KINGSUN_REQ_RECV;
738	kingsun->rx_setuprequest->wValue = cpu_to_le16(0x0200);
739	kingsun->rx_setuprequest->wIndex = 0;
740	kingsun->rx_setuprequest->wLength = cpu_to_le16(KINGSUN_RCV_FIFO_SIZE);
741
742	/* Allocate output buffer */
743	kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL);
744	if (!kingsun->tx_buf_clear)
745		goto free_mem;
746	kingsun->tx_buf_xored = kmalloc(KINGSUN_SND_PACKET_SIZE, GFP_KERNEL);
747	if (!kingsun->tx_buf_xored)
748		goto free_mem;
749
750	/* Allocate and initialize output setup packet */
751	kingsun->tx_setuprequest =
752	    kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
753	if (!kingsun->tx_setuprequest)
754		goto free_mem;
755	kingsun->tx_setuprequest->bRequestType =
756	    USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
757	kingsun->tx_setuprequest->bRequest = KINGSUN_REQ_SEND;
758	kingsun->tx_setuprequest->wValue = 0;
759	kingsun->tx_setuprequest->wIndex = 0;
760	kingsun->tx_setuprequest->wLength = 0;
761
762	/* Allocate and initialize speed setup packet */
763	kingsun->speed_setuprequest =
764	    kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
765	if (!kingsun->speed_setuprequest)
766		goto free_mem;
767	kingsun->speed_setuprequest->bRequestType =
768	    USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
769	kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND;
770	kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200);
771	kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001);
772	kingsun->speed_setuprequest->wLength =
773	    cpu_to_le16(sizeof(struct ks959_speedparams));
774
775	printk(KERN_INFO "KingSun KS-959 IRDA/USB found at address %d, "
776	       "Vendor: %x, Product: %x\n",
777	       dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
778	       le16_to_cpu(dev->descriptor.idProduct));
779
780	/* Initialize QoS for this device */
781	irda_init_max_qos_capabilies(&kingsun->qos);
782
783	/* Baud rates known to be supported. Please uncomment if devices (other
784	   than a SonyEriccson K300 phone) can be shown to support higher speed
785	   with this dongle.
786	 */
787	kingsun->qos.baud_rate.bits =
788	    IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600;
789	kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
790	irda_qos_bits_to_value(&kingsun->qos);
791
792	/* Override the network functions we need to use */
793	net->netdev_ops = &ks959_ops;
794
795	ret = register_netdev(net);
796	if (ret != 0)
797		goto free_mem;
798
799	dev_info(&net->dev, "IrDA: Registered KingSun KS-959 device %s\n",
800		 net->name);
801
802	usb_set_intfdata(intf, kingsun);
803
804	/* Situation at this point:
805	   - all work buffers allocated
806	   - setup requests pre-filled
807	   - urbs not allocated, set to NULL
808	   - max rx packet known (is KINGSUN_FIFO_SIZE)
809	   - unwrap state machine (partially) initialized, but skb == NULL
810	 */
811
812	return 0;
813
814      free_mem:
815	kfree(kingsun->speed_setuprequest);
816	kfree(kingsun->tx_setuprequest);
817	kfree(kingsun->tx_buf_xored);
818	kfree(kingsun->tx_buf_clear);
819	kfree(kingsun->rx_setuprequest);
820	kfree(kingsun->rx_buf);
821	free_netdev(net);
822      err_out1:
823	return ret;
824}
825
826/*
827 * The current device is removed, the USB layer tell us to shut it down...
828 */
829static void ks959_disconnect(struct usb_interface *intf)
830{
831	struct ks959_cb *kingsun = usb_get_intfdata(intf);
832
833	if (!kingsun)
834		return;
835
836	unregister_netdev(kingsun->netdev);
837
838	/* Mop up receive && transmit urb's */
839	if (kingsun->speed_urb != NULL) {
840		usb_kill_urb(kingsun->speed_urb);
841		usb_free_urb(kingsun->speed_urb);
842		kingsun->speed_urb = NULL;
843	}
844	if (kingsun->tx_urb != NULL) {
845		usb_kill_urb(kingsun->tx_urb);
846		usb_free_urb(kingsun->tx_urb);
847		kingsun->tx_urb = NULL;
848	}
849	if (kingsun->rx_urb != NULL) {
850		usb_kill_urb(kingsun->rx_urb);
851		usb_free_urb(kingsun->rx_urb);
852		kingsun->rx_urb = NULL;
853	}
854
855	kfree(kingsun->speed_setuprequest);
856	kfree(kingsun->tx_setuprequest);
857	kfree(kingsun->tx_buf_xored);
858	kfree(kingsun->tx_buf_clear);
859	kfree(kingsun->rx_setuprequest);
860	kfree(kingsun->rx_buf);
861	free_netdev(kingsun->netdev);
862
863	usb_set_intfdata(intf, NULL);
864}
865
866#ifdef CONFIG_PM
867/* USB suspend, so power off the transmitter/receiver */
868static int ks959_suspend(struct usb_interface *intf, pm_message_t message)
869{
870	struct ks959_cb *kingsun = usb_get_intfdata(intf);
871
872	netif_device_detach(kingsun->netdev);
873	if (kingsun->speed_urb != NULL)
874		usb_kill_urb(kingsun->speed_urb);
875	if (kingsun->tx_urb != NULL)
876		usb_kill_urb(kingsun->tx_urb);
877	if (kingsun->rx_urb != NULL)
878		usb_kill_urb(kingsun->rx_urb);
879	return 0;
880}
881
882/* Coming out of suspend, so reset hardware */
883static int ks959_resume(struct usb_interface *intf)
884{
885	struct ks959_cb *kingsun = usb_get_intfdata(intf);
886
887	if (kingsun->rx_urb != NULL) {
888		/* Setup request already filled in ks959_probe */
889		usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
890	}
891	netif_device_attach(kingsun->netdev);
892
893	return 0;
894}
895#endif
896
897/*
898 * USB device callbacks
899 */
900static struct usb_driver irda_driver = {
901	.name = "ks959-sir",
902	.probe = ks959_probe,
903	.disconnect = ks959_disconnect,
904	.id_table = dongles,
905#ifdef CONFIG_PM
906	.suspend = ks959_suspend,
907	.resume = ks959_resume,
908#endif
909};
910
911module_usb_driver(irda_driver);
912
913MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
914MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
915MODULE_LICENSE("GPL");