aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/irda
diff options
context:
space:
mode:
authorAlex Villacís Lasso <a_villacis@palosanto.com>2007-08-28 18:58:31 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:48:39 -0400
commit4b6aa59999a3a12dd4740a52299c6c33e85a8747 (patch)
tree827045fb6926c64d46af951fa07de398a5396e28 /drivers/net/irda
parent4a1d7c25cb438f96b700ac26dc5aa0a38a6d86ea (diff)
[IrDA]: Kingsun KS-959 IrDA USB driver
This dongle does not follow the usb-irda specification, so it needs its own special driver. First, it uses control URBs for data transfer, instead of bulk or interrupt transfers; the only interrupt endpoint exposed seems to be a dummy to prevent the interface from being rejected. Second, it uses obfuscation and padding at the USB traffic level, for no apparent reason other than to make reverse engineering harder (full details on obfuscation in comments at beginning of source). Although it is advertised as a "4 Mbps FIR dongle", it apparently loses packets at speeds greater than 57600 bps. On plugin, this dongle reports vendor and device IDs: 0x07d0:0x4959 . The Windows driver that is used normally to control this dongle has a filename of KS-959.SYS . Signed-off-by: Alex Villacís Lasso <a_villacis@palosanto.com> Signed-off-by: Samuel Ortiz <samuel@sortiz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/irda')
-rw-r--r--drivers/net/irda/Kconfig14
-rw-r--r--drivers/net/irda/Makefile1
-rw-r--r--drivers/net/irda/ks959-sir.c939
3 files changed, 954 insertions, 0 deletions
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index cfa7b8835d3d..65806956728a 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -176,6 +176,20 @@ config KSDAZZLE_DONGLE
176 To compile it as a module, choose M here: the module will be called 176 To compile it as a module, choose M here: the module will be called
177 ksdazzle-sir. 177 ksdazzle-sir.
178 178
179config KS959_DONGLE
180 tristate "KingSun KS-959 IrDA-USB dongle (EXPERIMENTAL)"
181 depends on IRDA && USB && EXPERIMENTAL
182 help
183 Say Y or M here if you want to build support for the KingSun KS-959
184 IrDA-USB bridge device driver.
185
186 This USB bridge does not conform to the IrDA-USB device class
187 specification, and therefore needs its own specific driver. This
188 dongle supports SIR speeds only (9600 through 57600 bps).
189
190 To compile it as a module, choose M here: the module will be called
191 ks959-sir.
192
179comment "Old SIR device drivers" 193comment "Old SIR device drivers"
180 194
181config IRPORT_SIR 195config IRPORT_SIR
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index e19da3b919a2..fefbb5909081 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o
48obj-$(CONFIG_EP7211_DONGLE) += ep7211-sir.o 48obj-$(CONFIG_EP7211_DONGLE) += ep7211-sir.o
49obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o 49obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o
50obj-$(CONFIG_KSDAZZLE_DONGLE) += ksdazzle-sir.o 50obj-$(CONFIG_KSDAZZLE_DONGLE) += ksdazzle-sir.o
51obj-$(CONFIG_KS959_DONGLE) += ks959-sir.o
51 52
52# The SIR helper module 53# The SIR helper module
53sir-dev-objs := sir_dev.o sir_dongle.o 54sir-dev-objs := sir_dev.o sir_dongle.o
diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c
new file mode 100644
index 000000000000..407afba1a597
--- /dev/null
+++ b/drivers/net/irda/ks959-sir.c
@@ -0,0 +1,939 @@
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/module.h>
122#include <linux/kref.h>
123#include <linux/usb.h>
124#include <linux/device.h>
125#include <linux/crc32.h>
126
127#include <asm/unaligned.h>
128#include <asm/byteorder.h>
129#include <asm/uaccess.h>
130
131#include <net/irda/irda.h>
132#include <net/irda/wrapper.h>
133#include <net/irda/crc.h>
134
135#define KS959_VENDOR_ID 0x07d0
136#define KS959_PRODUCT_ID 0x4959
137
138/* These are the currently known USB ids */
139static struct usb_device_id dongles[] = {
140 /* KingSun Co,Ltd IrDA/USB Bridge */
141 {USB_DEVICE(KS959_VENDOR_ID, KS959_PRODUCT_ID)},
142 {}
143};
144
145MODULE_DEVICE_TABLE(usb, dongles);
146
147#define KINGSUN_MTT 0x07
148#define KINGSUN_REQ_RECV 0x01
149#define KINGSUN_REQ_SEND 0x09
150
151#define KINGSUN_RCV_FIFO_SIZE 2048 /* Max length we can receive */
152#define KINGSUN_SND_FIFO_SIZE 2048 /* Max packet we can send */
153#define KINGSUN_SND_PACKET_SIZE 256 /* Max packet dongle can handle */
154
155struct ks959_speedparams {
156 __le32 baudrate; /* baud rate, little endian */
157 __u8 flags;
158 __u8 reserved[3];
159} __attribute__ ((packed));
160
161#define KS_DATA_5_BITS 0x00
162#define KS_DATA_6_BITS 0x01
163#define KS_DATA_7_BITS 0x02
164#define KS_DATA_8_BITS 0x03
165
166#define KS_STOP_BITS_1 0x00
167#define KS_STOP_BITS_2 0x08
168
169#define KS_PAR_DISABLE 0x00
170#define KS_PAR_EVEN 0x10
171#define KS_PAR_ODD 0x30
172#define KS_RESET 0x80
173
174struct ks959_cb {
175 struct usb_device *usbdev; /* init: probe_irda */
176 struct net_device *netdev; /* network layer */
177 struct irlap_cb *irlap; /* The link layer we are binded to */
178 struct net_device_stats stats; /* network statistics */
179 struct qos_info qos;
180
181 struct usb_ctrlrequest *tx_setuprequest;
182 struct urb *tx_urb;
183 __u8 *tx_buf_clear;
184 unsigned int tx_buf_clear_used;
185 unsigned int tx_buf_clear_sent;
186 __u8 *tx_buf_xored;
187
188 struct usb_ctrlrequest *rx_setuprequest;
189 struct urb *rx_urb;
190 __u8 *rx_buf;
191 __u8 rx_variable_xormask;
192 iobuff_t rx_unwrap_buff;
193 struct timeval rx_time;
194
195 struct usb_ctrlrequest *speed_setuprequest;
196 struct urb *speed_urb;
197 struct ks959_speedparams speedparams;
198 unsigned int new_speed;
199
200 spinlock_t lock;
201 int receiving;
202};
203
204/* Procedure to perform the obfuscation/padding expected by the dongle
205 *
206 * buf_cleartext (IN) Cleartext version of the IrDA frame to transmit
207 * len_cleartext (IN) Length of the cleartext version of IrDA frame
208 * buf_xoredtext (OUT) Obfuscated version of frame built by proc
209 * len_maxbuf (OUT) Maximum space available at buf_xoredtext
210 *
211 * (return) length of obfuscated frame with padding
212 *
213 * If not enough space (as indicated by len_maxbuf vs. required padding),
214 * zero is returned
215 *
216 * The value of lookup_string is actually a required portion of the algorithm.
217 * Seems the designer of the dongle wanted to state who exactly is responsible
218 * for implementing obfuscation. Send your best (or other) wishes to him ]:-)
219 */
220static unsigned int obfuscate_tx_buffer(const __u8 * buf_cleartext,
221 unsigned int len_cleartext,
222 __u8 * buf_xoredtext,
223 unsigned int len_maxbuf)
224{
225 unsigned int len_xoredtext;
226
227 /* Calculate required length with padding, check for necessary space */
228 len_xoredtext = ((len_cleartext + 7) & ~0x7) + 0x10;
229 if (len_xoredtext <= len_maxbuf) {
230 static const __u8 lookup_string[] = "wangshuofei19710";
231 __u8 xor_mask;
232
233 /* Unlike the WinXP driver, we *do* clear out the padding */
234 memset(buf_xoredtext, 0, len_xoredtext);
235
236 xor_mask = lookup_string[(len_cleartext & 0x0f) ^ 0x06] ^ 0x55;
237
238 while (len_cleartext-- > 0) {
239 *buf_xoredtext++ = *buf_cleartext++ ^ xor_mask;
240 }
241 } else {
242 len_xoredtext = 0;
243 }
244 return len_xoredtext;
245}
246
247/* Callback transmission routine */
248static void ks959_speed_irq(struct urb *urb)
249{
250 /* unlink, shutdown, unplug, other nasties */
251 if (urb->status != 0) {
252 err("ks959_speed_irq: urb asynchronously failed - %d",
253 urb->status);
254 }
255}
256
257/* Send a control request to change speed of the dongle */
258static int ks959_change_speed(struct ks959_cb *kingsun, unsigned speed)
259{
260 static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400,
261 57600, 115200, 576000, 1152000, 4000000, 0
262 };
263 int err;
264 unsigned int i;
265
266 if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL)
267 return -ENOMEM;
268
269 /* Check that requested speed is among the supported ones */
270 for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ;
271 if (supported_speeds[i] == 0)
272 return -EOPNOTSUPP;
273
274 memset(&(kingsun->speedparams), 0, sizeof(struct ks959_speedparams));
275 kingsun->speedparams.baudrate = cpu_to_le32(speed);
276 kingsun->speedparams.flags = KS_DATA_8_BITS;
277
278 /* speed_setuprequest pre-filled in ks959_probe */
279 usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev,
280 usb_sndctrlpipe(kingsun->usbdev, 0),
281 (unsigned char *)kingsun->speed_setuprequest,
282 &(kingsun->speedparams),
283 sizeof(struct ks959_speedparams), ks959_speed_irq,
284 kingsun);
285 kingsun->speed_urb->status = 0;
286 err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC);
287
288 return err;
289}
290
291/* Submit one fragment of an IrDA frame to the dongle */
292static void ks959_send_irq(struct urb *urb);
293static int ks959_submit_tx_fragment(struct ks959_cb *kingsun)
294{
295 unsigned int padlen;
296 unsigned int wraplen;
297 int ret;
298
299 /* Check whether current plaintext can produce a padded buffer that fits
300 within the range handled by the dongle */
301 wraplen = (KINGSUN_SND_PACKET_SIZE & ~0x7) - 0x10;
302 if (wraplen > kingsun->tx_buf_clear_used)
303 wraplen = kingsun->tx_buf_clear_used;
304
305 /* Perform dongle obfuscation. Also remove the portion of the frame that
306 was just obfuscated and will now be sent to the dongle. */
307 padlen = obfuscate_tx_buffer(kingsun->tx_buf_clear, wraplen,
308 kingsun->tx_buf_xored,
309 KINGSUN_SND_PACKET_SIZE);
310
311 /* Calculate how much data can be transmitted in this urb */
312 kingsun->tx_setuprequest->wValue = cpu_to_le16(wraplen);
313 kingsun->tx_setuprequest->wLength = cpu_to_le16(padlen);
314 /* Rest of the fields were filled in ks959_probe */
315 usb_fill_control_urb(kingsun->tx_urb, kingsun->usbdev,
316 usb_sndctrlpipe(kingsun->usbdev, 0),
317 (unsigned char *)kingsun->tx_setuprequest,
318 kingsun->tx_buf_xored, padlen,
319 ks959_send_irq, kingsun);
320 kingsun->tx_urb->status = 0;
321 ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC);
322
323 /* Remember how much data was sent, in order to update at callback */
324 kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0;
325 return ret;
326}
327
328/* Callback transmission routine */
329static void ks959_send_irq(struct urb *urb)
330{
331 struct ks959_cb *kingsun = urb->context;
332 struct net_device *netdev = kingsun->netdev;
333 int ret = 0;
334
335 /* in process of stopping, just drop data */
336 if (!netif_running(kingsun->netdev)) {
337 err("ks959_send_irq: Network not running!");
338 return;
339 }
340
341 /* unlink, shutdown, unplug, other nasties */
342 if (urb->status != 0) {
343 err("ks959_send_irq: urb asynchronously failed - %d",
344 urb->status);
345 return;
346 }
347
348 if (kingsun->tx_buf_clear_used > 0) {
349 /* Update data remaining to be sent */
350 if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) {
351 memmove(kingsun->tx_buf_clear,
352 kingsun->tx_buf_clear +
353 kingsun->tx_buf_clear_sent,
354 kingsun->tx_buf_clear_used -
355 kingsun->tx_buf_clear_sent);
356 }
357 kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent;
358 kingsun->tx_buf_clear_sent = 0;
359
360 if (kingsun->tx_buf_clear_used > 0) {
361 /* There is more data to be sent */
362 if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) {
363 err("ks959_send_irq: failed tx_urb submit: %d",
364 ret);
365 switch (ret) {
366 case -ENODEV:
367 case -EPIPE:
368 break;
369 default:
370 kingsun->stats.tx_errors++;
371 netif_start_queue(netdev);
372 }
373 }
374 } else {
375 /* All data sent, send next speed && wake network queue */
376 if (kingsun->new_speed != -1 &&
377 cpu_to_le32(kingsun->new_speed) !=
378 kingsun->speedparams.baudrate)
379 ks959_change_speed(kingsun, kingsun->new_speed);
380
381 netif_wake_queue(netdev);
382 }
383 }
384}
385
386/*
387 * Called from net/core when new frame is available.
388 */
389static int ks959_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
390{
391 struct ks959_cb *kingsun;
392 unsigned int wraplen;
393 int ret = 0;
394
395 if (skb == NULL || netdev == NULL)
396 return -EINVAL;
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 err("ks959_hard_xmit: failed tx_urb submit: %d", ret);
415 switch (ret) {
416 case -ENODEV:
417 case -EPIPE:
418 break;
419 default:
420 kingsun->stats.tx_errors++;
421 netif_start_queue(netdev);
422 }
423 } else {
424 kingsun->stats.tx_packets++;
425 kingsun->stats.tx_bytes += skb->len;
426
427 }
428
429 dev_kfree_skb(skb);
430 spin_unlock(&kingsun->lock);
431
432 return ret;
433}
434
435/* Receive callback function */
436static void ks959_rcv_irq(struct urb *urb)
437{
438 struct ks959_cb *kingsun = urb->context;
439 int ret;
440
441 /* in process of stopping, just drop data */
442 if (!netif_running(kingsun->netdev)) {
443 kingsun->receiving = 0;
444 return;
445 }
446
447 /* unlink, shutdown, unplug, other nasties */
448 if (urb->status != 0) {
449 err("kingsun_rcv_irq: urb asynchronously failed - %d",
450 urb->status);
451 kingsun->receiving = 0;
452 return;
453 }
454
455 if (urb->actual_length > 0) {
456 __u8 *bytes = urb->transfer_buffer;
457 unsigned int i;
458
459 for (i = 0; i < urb->actual_length; i++) {
460 /* De-obfuscation implemented here: variable portion of
461 xormask is incremented, and then used with the encoded
462 byte for the XOR. The result of the operation is used
463 to unwrap the SIR frame. */
464 kingsun->rx_variable_xormask++;
465 bytes[i] =
466 bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u;
467
468 /* rx_variable_xormask doubles as an index counter so we
469 can skip the byte at 0xff (wrapped around to 0).
470 */
471 if (kingsun->rx_variable_xormask != 0) {
472 async_unwrap_char(kingsun->netdev,
473 &kingsun->stats,
474 &kingsun->rx_unwrap_buff,
475 bytes[i]);
476 }
477 }
478 kingsun->netdev->last_rx = jiffies;
479 do_gettimeofday(&kingsun->rx_time);
480 kingsun->receiving =
481 (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
482 }
483
484 /* This urb has already been filled in kingsun_net_open. Setup
485 packet must be re-filled, but it is assumed that urb keeps the
486 pointer to the initial setup packet, as well as the payload buffer.
487 Setup packet is already pre-filled at ks959_probe.
488 */
489 urb->status = 0;
490 ret = usb_submit_urb(urb, GFP_ATOMIC);
491}
492
493/*
494 * Function kingsun_net_open (dev)
495 *
496 * Network device is taken up. Usually this is done by "ifconfig irda0 up"
497 */
498static int ks959_net_open(struct net_device *netdev)
499{
500 struct ks959_cb *kingsun = netdev_priv(netdev);
501 int err = -ENOMEM;
502 char hwname[16];
503
504 /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
505 kingsun->receiving = 0;
506
507 /* Initialize for SIR to copy data directly into skb. */
508 kingsun->rx_unwrap_buff.in_frame = FALSE;
509 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
510 kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU;
511 kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
512 if (!kingsun->rx_unwrap_buff.skb)
513 goto free_mem;
514
515 skb_reserve(kingsun->rx_unwrap_buff.skb, 1);
516 kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data;
517 do_gettimeofday(&kingsun->rx_time);
518
519 kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
520 if (!kingsun->rx_urb)
521 goto free_mem;
522
523 kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
524 if (!kingsun->tx_urb)
525 goto free_mem;
526
527 kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL);
528 if (!kingsun->speed_urb)
529 goto free_mem;
530
531 /* Initialize speed for dongle */
532 kingsun->new_speed = 9600;
533 err = ks959_change_speed(kingsun, 9600);
534 if (err < 0)
535 goto free_mem;
536
537 /*
538 * Now that everything should be initialized properly,
539 * Open new IrLAP layer instance to take care of us...
540 */
541 sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
542 kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
543 if (!kingsun->irlap) {
544 err("ks959-sir: irlap_open failed");
545 goto free_mem;
546 }
547
548 /* Start reception. Setup request already pre-filled in ks959_probe */
549 usb_fill_control_urb(kingsun->rx_urb, kingsun->usbdev,
550 usb_rcvctrlpipe(kingsun->usbdev, 0),
551 (unsigned char *)kingsun->rx_setuprequest,
552 kingsun->rx_buf, KINGSUN_RCV_FIFO_SIZE,
553 ks959_rcv_irq, kingsun);
554 kingsun->rx_urb->status = 0;
555 err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
556 if (err) {
557 err("ks959-sir: first urb-submit failed: %d", err);
558 goto close_irlap;
559 }
560
561 netif_start_queue(netdev);
562
563 /* Situation at this point:
564 - all work buffers allocated
565 - urbs allocated and ready to fill
566 - max rx packet known (in max_rx)
567 - unwrap state machine initialized, in state outside of any frame
568 - receive request in progress
569 - IrLAP layer started, about to hand over packets to send
570 */
571
572 return 0;
573
574 close_irlap:
575 irlap_close(kingsun->irlap);
576 free_mem:
577 usb_free_urb(kingsun->speed_urb);
578 kingsun->speed_urb = NULL;
579 usb_free_urb(kingsun->tx_urb);
580 kingsun->tx_urb = NULL;
581 usb_free_urb(kingsun->rx_urb);
582 kingsun->rx_urb = NULL;
583 if (kingsun->rx_unwrap_buff.skb) {
584 kfree_skb(kingsun->rx_unwrap_buff.skb);
585 kingsun->rx_unwrap_buff.skb = NULL;
586 kingsun->rx_unwrap_buff.head = NULL;
587 }
588 return err;
589}
590
591/*
592 * Function kingsun_net_close (kingsun)
593 *
594 * Network device is taken down. Usually this is done by
595 * "ifconfig irda0 down"
596 */
597static int ks959_net_close(struct net_device *netdev)
598{
599 struct ks959_cb *kingsun = netdev_priv(netdev);
600
601 /* Stop transmit processing */
602 netif_stop_queue(netdev);
603
604 /* Mop up receive && transmit urb's */
605 usb_kill_urb(kingsun->tx_urb);
606 usb_free_urb(kingsun->tx_urb);
607 kingsun->tx_urb = NULL;
608
609 usb_kill_urb(kingsun->speed_urb);
610 usb_free_urb(kingsun->speed_urb);
611 kingsun->speed_urb = NULL;
612
613 usb_kill_urb(kingsun->rx_urb);
614 usb_free_urb(kingsun->rx_urb);
615 kingsun->rx_urb = NULL;
616
617 kfree_skb(kingsun->rx_unwrap_buff.skb);
618 kingsun->rx_unwrap_buff.skb = NULL;
619 kingsun->rx_unwrap_buff.head = NULL;
620 kingsun->rx_unwrap_buff.in_frame = FALSE;
621 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
622 kingsun->receiving = 0;
623
624 /* Stop and remove instance of IrLAP */
625 if (kingsun->irlap)
626 irlap_close(kingsun->irlap);
627
628 kingsun->irlap = NULL;
629
630 return 0;
631}
632
633/*
634 * IOCTLs : Extra out-of-band network commands...
635 */
636static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
637{
638 struct if_irda_req *irq = (struct if_irda_req *)rq;
639 struct ks959_cb *kingsun = netdev_priv(netdev);
640 int ret = 0;
641
642 switch (cmd) {
643 case SIOCSBANDWIDTH: /* Set bandwidth */
644 if (!capable(CAP_NET_ADMIN))
645 return -EPERM;
646
647 /* Check if the device is still there */
648 if (netif_device_present(kingsun->netdev))
649 return ks959_change_speed(kingsun, irq->ifr_baudrate);
650 break;
651
652 case SIOCSMEDIABUSY: /* Set media busy */
653 if (!capable(CAP_NET_ADMIN))
654 return -EPERM;
655
656 /* Check if the IrDA stack is still there */
657 if (netif_running(kingsun->netdev))
658 irda_device_set_media_busy(kingsun->netdev, TRUE);
659 break;
660
661 case SIOCGRECEIVING:
662 /* Only approximately true */
663 irq->ifr_receiving = kingsun->receiving;
664 break;
665
666 default:
667 ret = -EOPNOTSUPP;
668 }
669
670 return ret;
671}
672
673/*
674 * Get device stats (for /proc/net/dev and ifconfig)
675 */
676static struct net_device_stats *ks959_net_get_stats(struct net_device *netdev)
677{
678 struct ks959_cb *kingsun = netdev_priv(netdev);
679 return &kingsun->stats;
680}
681
682/*
683 * This routine is called by the USB subsystem for each new device
684 * in the system. We need to check if the device is ours, and in
685 * this case start handling it.
686 */
687static int ks959_probe(struct usb_interface *intf,
688 const struct usb_device_id *id)
689{
690 struct usb_device *dev = interface_to_usbdev(intf);
691 struct ks959_cb *kingsun = NULL;
692 struct net_device *net = NULL;
693 int ret = -ENOMEM;
694
695 /* Allocate network device container. */
696 net = alloc_irdadev(sizeof(*kingsun));
697 if (!net)
698 goto err_out1;
699
700 SET_MODULE_OWNER(net);
701 SET_NETDEV_DEV(net, &intf->dev);
702 kingsun = netdev_priv(net);
703 kingsun->netdev = net;
704 kingsun->usbdev = dev;
705 kingsun->irlap = NULL;
706 kingsun->tx_setuprequest = NULL;
707 kingsun->tx_urb = NULL;
708 kingsun->tx_buf_clear = NULL;
709 kingsun->tx_buf_xored = NULL;
710 kingsun->tx_buf_clear_used = 0;
711 kingsun->tx_buf_clear_sent = 0;
712
713 kingsun->rx_setuprequest = NULL;
714 kingsun->rx_urb = NULL;
715 kingsun->rx_buf = NULL;
716 kingsun->rx_variable_xormask = 0;
717 kingsun->rx_unwrap_buff.in_frame = FALSE;
718 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
719 kingsun->rx_unwrap_buff.skb = NULL;
720 kingsun->receiving = 0;
721 spin_lock_init(&kingsun->lock);
722
723 kingsun->speed_setuprequest = NULL;
724 kingsun->speed_urb = NULL;
725 kingsun->speedparams.baudrate = 0;
726
727 /* Allocate input buffer */
728 kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL);
729 if (!kingsun->rx_buf)
730 goto free_mem;
731
732 /* Allocate input setup packet */
733 kingsun->rx_setuprequest =
734 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
735 if (!kingsun->rx_setuprequest)
736 goto free_mem;
737 kingsun->rx_setuprequest->bRequestType =
738 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
739 kingsun->rx_setuprequest->bRequest = KINGSUN_REQ_RECV;
740 kingsun->rx_setuprequest->wValue = cpu_to_le16(0x0200);
741 kingsun->rx_setuprequest->wIndex = 0;
742 kingsun->rx_setuprequest->wLength = cpu_to_le16(KINGSUN_RCV_FIFO_SIZE);
743
744 /* Allocate output buffer */
745 kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL);
746 if (!kingsun->tx_buf_clear)
747 goto free_mem;
748 kingsun->tx_buf_xored = kmalloc(KINGSUN_SND_PACKET_SIZE, GFP_KERNEL);
749 if (!kingsun->tx_buf_xored)
750 goto free_mem;
751
752 /* Allocate and initialize output setup packet */
753 kingsun->tx_setuprequest =
754 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
755 if (!kingsun->tx_setuprequest)
756 goto free_mem;
757 kingsun->tx_setuprequest->bRequestType =
758 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
759 kingsun->tx_setuprequest->bRequest = KINGSUN_REQ_SEND;
760 kingsun->tx_setuprequest->wValue = 0;
761 kingsun->tx_setuprequest->wIndex = 0;
762 kingsun->tx_setuprequest->wLength = 0;
763
764 /* Allocate and initialize speed setup packet */
765 kingsun->speed_setuprequest =
766 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
767 if (!kingsun->speed_setuprequest)
768 goto free_mem;
769 kingsun->speed_setuprequest->bRequestType =
770 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
771 kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND;
772 kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200);
773 kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001);
774 kingsun->speed_setuprequest->wLength =
775 cpu_to_le16(sizeof(struct ks959_speedparams));
776
777 printk(KERN_INFO "KingSun KS-959 IRDA/USB found at address %d, "
778 "Vendor: %x, Product: %x\n",
779 dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
780 le16_to_cpu(dev->descriptor.idProduct));
781
782 /* Initialize QoS for this device */
783 irda_init_max_qos_capabilies(&kingsun->qos);
784
785 /* Baud rates known to be supported. Please uncomment if devices (other
786 than a SonyEriccson K300 phone) can be shown to support higher speed
787 with this dongle.
788 */
789 kingsun->qos.baud_rate.bits =
790 IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600;
791 kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
792 irda_qos_bits_to_value(&kingsun->qos);
793
794 /* Override the network functions we need to use */
795 net->hard_start_xmit = ks959_hard_xmit;
796 net->open = ks959_net_open;
797 net->stop = ks959_net_close;
798 net->get_stats = ks959_net_get_stats;
799 net->do_ioctl = ks959_net_ioctl;
800
801 ret = register_netdev(net);
802 if (ret != 0)
803 goto free_mem;
804
805 info("IrDA: Registered KingSun KS-959 device %s", net->name);
806
807 usb_set_intfdata(intf, kingsun);
808
809 /* Situation at this point:
810 - all work buffers allocated
811 - setup requests pre-filled
812 - urbs not allocated, set to NULL
813 - max rx packet known (is KINGSUN_FIFO_SIZE)
814 - unwrap state machine (partially) initialized, but skb == NULL
815 */
816
817 return 0;
818
819 free_mem:
820 kfree(kingsun->speed_setuprequest);
821 kfree(kingsun->tx_setuprequest);
822 kfree(kingsun->tx_buf_xored);
823 kfree(kingsun->tx_buf_clear);
824 kfree(kingsun->rx_setuprequest);
825 kfree(kingsun->rx_buf);
826 free_netdev(net);
827 err_out1:
828 return ret;
829}
830
831/*
832 * The current device is removed, the USB layer tell us to shut it down...
833 */
834static void ks959_disconnect(struct usb_interface *intf)
835{
836 struct ks959_cb *kingsun = usb_get_intfdata(intf);
837
838 if (!kingsun)
839 return;
840
841 unregister_netdev(kingsun->netdev);
842
843 /* Mop up receive && transmit urb's */
844 if (kingsun->speed_urb != NULL) {
845 usb_kill_urb(kingsun->speed_urb);
846 usb_free_urb(kingsun->speed_urb);
847 kingsun->speed_urb = NULL;
848 }
849 if (kingsun->tx_urb != NULL) {
850 usb_kill_urb(kingsun->tx_urb);
851 usb_free_urb(kingsun->tx_urb);
852 kingsun->tx_urb = NULL;
853 }
854 if (kingsun->rx_urb != NULL) {
855 usb_kill_urb(kingsun->rx_urb);
856 usb_free_urb(kingsun->rx_urb);
857 kingsun->rx_urb = NULL;
858 }
859
860 kfree(kingsun->speed_setuprequest);
861 kfree(kingsun->tx_setuprequest);
862 kfree(kingsun->tx_buf_xored);
863 kfree(kingsun->tx_buf_clear);
864 kfree(kingsun->rx_setuprequest);
865 kfree(kingsun->rx_buf);
866 free_netdev(kingsun->netdev);
867
868 usb_set_intfdata(intf, NULL);
869}
870
871#ifdef CONFIG_PM
872/* USB suspend, so power off the transmitter/receiver */
873static int ks959_suspend(struct usb_interface *intf, pm_message_t message)
874{
875 struct ks959_cb *kingsun = usb_get_intfdata(intf);
876
877 netif_device_detach(kingsun->netdev);
878 if (kingsun->speed_urb != NULL)
879 usb_kill_urb(kingsun->speed_urb);
880 if (kingsun->tx_urb != NULL)
881 usb_kill_urb(kingsun->tx_urb);
882 if (kingsun->rx_urb != NULL)
883 usb_kill_urb(kingsun->rx_urb);
884 return 0;
885}
886
887/* Coming out of suspend, so reset hardware */
888static int ks959_resume(struct usb_interface *intf)
889{
890 struct ks959_cb *kingsun = usb_get_intfdata(intf);
891
892 if (kingsun->rx_urb != NULL) {
893 /* Setup request already filled in ks959_probe */
894 usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
895 }
896 netif_device_attach(kingsun->netdev);
897
898 return 0;
899}
900#endif
901
902/*
903 * USB device callbacks
904 */
905static struct usb_driver irda_driver = {
906 .name = "ks959-sir",
907 .probe = ks959_probe,
908 .disconnect = ks959_disconnect,
909 .id_table = dongles,
910#ifdef CONFIG_PM
911 .suspend = ks959_suspend,
912 .resume = ks959_resume,
913#endif
914};
915
916/*
917 * Module insertion
918 */
919static int __init ks959_init(void)
920{
921 return usb_register(&irda_driver);
922}
923
924module_init(ks959_init);
925
926/*
927 * Module removal
928 */
929static void __exit ks959_cleanup(void)
930{
931 /* Deregister the driver and remove all pending instances */
932 usb_deregister(&irda_driver);
933}
934
935module_exit(ks959_cleanup);
936
937MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
938MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
939MODULE_LICENSE("GPL");