blob: 5f3aeac3f86df57e297b1559a5bda2b7669145a9 [file] [log] [blame]
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -07001/*****************************************************************************
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>
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700121#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];
Eric Dumazetba2d3582010-06-02 18:10:09 +0000157} __packed;
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700158
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 */
Stephen Hemmingeraf049082009-01-06 10:40:43 -0800176
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700177 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) {
Greg Kroah-Hartman32279242012-04-25 14:48:50 -0700250 dev_err(&urb->dev->dev,
251 "ks959_speed_irq: urb asynchronously failed - %d\n",
252 urb->status);
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700253 }
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)) {
Greg Kroah-Hartman32279242012-04-25 14:48:50 -0700336 dev_err(&kingsun->usbdev->dev,
337 "ks959_send_irq: Network not running!\n");
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700338 return;
339 }
340
341 /* unlink, shutdown, unplug, other nasties */
342 if (urb->status != 0) {
Greg Kroah-Hartman32279242012-04-25 14:48:50 -0700343 dev_err(&kingsun->usbdev->dev,
344 "ks959_send_irq: urb asynchronously failed - %d\n",
345 urb->status);
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700346 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) {
Greg Kroah-Hartman32279242012-04-25 14:48:50 -0700364 dev_err(&kingsun->usbdev->dev,
365 "ks959_send_irq: failed tx_urb submit: %d\n",
366 ret);
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700367 switch (ret) {
368 case -ENODEV:
369 case -EPIPE:
370 break;
371 default:
Stephen Hemmingeraf049082009-01-06 10:40:43 -0800372 netdev->stats.tx_errors++;
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700373 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 */
Stephen Hemminger6518bbb2009-08-31 19:50:50 +0000391static netdev_tx_t ks959_hard_xmit(struct sk_buff *skb,
392 struct net_device *netdev)
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700393{
394 struct ks959_cb *kingsun;
395 unsigned int wraplen;
396 int ret = 0;
397
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700398 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) {
Greg Kroah-Hartman32279242012-04-25 14:48:50 -0700414 dev_err(&kingsun->usbdev->dev,
415 "ks959_hard_xmit: failed tx_urb submit: %d\n", ret);
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700416 switch (ret) {
417 case -ENODEV:
418 case -EPIPE:
419 break;
420 default:
Stephen Hemmingeraf049082009-01-06 10:40:43 -0800421 netdev->stats.tx_errors++;
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700422 netif_start_queue(netdev);
423 }
424 } else {
Stephen Hemmingeraf049082009-01-06 10:40:43 -0800425 netdev->stats.tx_packets++;
426 netdev->stats.tx_bytes += skb->len;
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700427
428 }
429
430 dev_kfree_skb(skb);
431 spin_unlock(&kingsun->lock);
432
Patrick McHardy4bd73ae2009-06-12 03:17:19 +0000433 return NETDEV_TX_OK;
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700434}
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) {
Greg Kroah-Hartman32279242012-04-25 14:48:50 -0700450 dev_err(&kingsun->usbdev->dev,
451 "kingsun_rcv_irq: urb asynchronously failed - %d\n",
452 urb->status);
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700453 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,
Stephen Hemmingeraf049082009-01-06 10:40:43 -0800475 &kingsun->netdev->stats,
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700476 &kingsun->rx_unwrap_buff,
477 bytes[i]);
478 }
479 }
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700480 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) {
Julia Lawall9915e672012-08-16 21:46:58 +0000545 err = -ENOMEM;
Greg Kroah-Hartman32279242012-04-25 14:48:50 -0700546 dev_err(&kingsun->usbdev->dev, "irlap_open failed\n");
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700547 goto free_mem;
548 }
549
550 /* Start reception. Setup request already pre-filled in ks959_probe */
551 usb_fill_control_urb(kingsun->rx_urb, kingsun->usbdev,
552 usb_rcvctrlpipe(kingsun->usbdev, 0),
553 (unsigned char *)kingsun->rx_setuprequest,
554 kingsun->rx_buf, KINGSUN_RCV_FIFO_SIZE,
555 ks959_rcv_irq, kingsun);
556 kingsun->rx_urb->status = 0;
557 err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
558 if (err) {
Greg Kroah-Hartman32279242012-04-25 14:48:50 -0700559 dev_err(&kingsun->usbdev->dev,
560 "first urb-submit failed: %d\n", err);
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700561 goto close_irlap;
562 }
563
564 netif_start_queue(netdev);
565
566 /* Situation at this point:
567 - all work buffers allocated
568 - urbs allocated and ready to fill
569 - max rx packet known (in max_rx)
570 - unwrap state machine initialized, in state outside of any frame
571 - receive request in progress
572 - IrLAP layer started, about to hand over packets to send
573 */
574
575 return 0;
576
577 close_irlap:
578 irlap_close(kingsun->irlap);
579 free_mem:
580 usb_free_urb(kingsun->speed_urb);
581 kingsun->speed_urb = NULL;
582 usb_free_urb(kingsun->tx_urb);
583 kingsun->tx_urb = NULL;
584 usb_free_urb(kingsun->rx_urb);
585 kingsun->rx_urb = NULL;
586 if (kingsun->rx_unwrap_buff.skb) {
587 kfree_skb(kingsun->rx_unwrap_buff.skb);
588 kingsun->rx_unwrap_buff.skb = NULL;
589 kingsun->rx_unwrap_buff.head = NULL;
590 }
591 return err;
592}
593
594/*
595 * Function kingsun_net_close (kingsun)
596 *
597 * Network device is taken down. Usually this is done by
598 * "ifconfig irda0 down"
599 */
600static int ks959_net_close(struct net_device *netdev)
601{
602 struct ks959_cb *kingsun = netdev_priv(netdev);
603
604 /* Stop transmit processing */
605 netif_stop_queue(netdev);
606
607 /* Mop up receive && transmit urb's */
608 usb_kill_urb(kingsun->tx_urb);
609 usb_free_urb(kingsun->tx_urb);
610 kingsun->tx_urb = NULL;
611
612 usb_kill_urb(kingsun->speed_urb);
613 usb_free_urb(kingsun->speed_urb);
614 kingsun->speed_urb = NULL;
615
616 usb_kill_urb(kingsun->rx_urb);
617 usb_free_urb(kingsun->rx_urb);
618 kingsun->rx_urb = NULL;
619
620 kfree_skb(kingsun->rx_unwrap_buff.skb);
621 kingsun->rx_unwrap_buff.skb = NULL;
622 kingsun->rx_unwrap_buff.head = NULL;
623 kingsun->rx_unwrap_buff.in_frame = FALSE;
624 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
625 kingsun->receiving = 0;
626
627 /* Stop and remove instance of IrLAP */
628 if (kingsun->irlap)
629 irlap_close(kingsun->irlap);
630
631 kingsun->irlap = NULL;
632
633 return 0;
634}
635
636/*
637 * IOCTLs : Extra out-of-band network commands...
638 */
639static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
640{
641 struct if_irda_req *irq = (struct if_irda_req *)rq;
642 struct ks959_cb *kingsun = netdev_priv(netdev);
643 int ret = 0;
644
645 switch (cmd) {
646 case SIOCSBANDWIDTH: /* Set bandwidth */
647 if (!capable(CAP_NET_ADMIN))
648 return -EPERM;
649
650 /* Check if the device is still there */
651 if (netif_device_present(kingsun->netdev))
652 return ks959_change_speed(kingsun, irq->ifr_baudrate);
653 break;
654
655 case SIOCSMEDIABUSY: /* Set media busy */
656 if (!capable(CAP_NET_ADMIN))
657 return -EPERM;
658
659 /* Check if the IrDA stack is still there */
660 if (netif_running(kingsun->netdev))
661 irda_device_set_media_busy(kingsun->netdev, TRUE);
662 break;
663
664 case SIOCGRECEIVING:
665 /* Only approximately true */
666 irq->ifr_receiving = kingsun->receiving;
667 break;
668
669 default:
670 ret = -EOPNOTSUPP;
671 }
672
673 return ret;
674}
675
Stephen Hemminger94ffab62009-03-20 19:35:47 +0000676static const struct net_device_ops ks959_ops = {
677 .ndo_start_xmit = ks959_hard_xmit,
678 .ndo_open = ks959_net_open,
679 .ndo_stop = ks959_net_close,
680 .ndo_do_ioctl = ks959_net_ioctl,
681};
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700682/*
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700683 * 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
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700700 SET_NETDEV_DEV(net, &intf->dev);
701 kingsun = netdev_priv(net);
702 kingsun->netdev = net;
703 kingsun->usbdev = dev;
704 kingsun->irlap = NULL;
705 kingsun->tx_setuprequest = NULL;
706 kingsun->tx_urb = NULL;
707 kingsun->tx_buf_clear = NULL;
708 kingsun->tx_buf_xored = NULL;
709 kingsun->tx_buf_clear_used = 0;
710 kingsun->tx_buf_clear_sent = 0;
711
712 kingsun->rx_setuprequest = NULL;
713 kingsun->rx_urb = NULL;
714 kingsun->rx_buf = NULL;
715 kingsun->rx_variable_xormask = 0;
716 kingsun->rx_unwrap_buff.in_frame = FALSE;
717 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME;
718 kingsun->rx_unwrap_buff.skb = NULL;
719 kingsun->receiving = 0;
720 spin_lock_init(&kingsun->lock);
721
722 kingsun->speed_setuprequest = NULL;
723 kingsun->speed_urb = NULL;
724 kingsun->speedparams.baudrate = 0;
725
726 /* Allocate input buffer */
727 kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL);
728 if (!kingsun->rx_buf)
729 goto free_mem;
730
731 /* Allocate input setup packet */
732 kingsun->rx_setuprequest =
733 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
734 if (!kingsun->rx_setuprequest)
735 goto free_mem;
736 kingsun->rx_setuprequest->bRequestType =
737 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
738 kingsun->rx_setuprequest->bRequest = KINGSUN_REQ_RECV;
739 kingsun->rx_setuprequest->wValue = cpu_to_le16(0x0200);
740 kingsun->rx_setuprequest->wIndex = 0;
741 kingsun->rx_setuprequest->wLength = cpu_to_le16(KINGSUN_RCV_FIFO_SIZE);
742
743 /* Allocate output buffer */
744 kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL);
745 if (!kingsun->tx_buf_clear)
746 goto free_mem;
747 kingsun->tx_buf_xored = kmalloc(KINGSUN_SND_PACKET_SIZE, GFP_KERNEL);
748 if (!kingsun->tx_buf_xored)
749 goto free_mem;
750
751 /* Allocate and initialize output setup packet */
752 kingsun->tx_setuprequest =
753 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
754 if (!kingsun->tx_setuprequest)
755 goto free_mem;
756 kingsun->tx_setuprequest->bRequestType =
757 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
758 kingsun->tx_setuprequest->bRequest = KINGSUN_REQ_SEND;
759 kingsun->tx_setuprequest->wValue = 0;
760 kingsun->tx_setuprequest->wIndex = 0;
761 kingsun->tx_setuprequest->wLength = 0;
762
763 /* Allocate and initialize speed setup packet */
764 kingsun->speed_setuprequest =
765 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
766 if (!kingsun->speed_setuprequest)
767 goto free_mem;
768 kingsun->speed_setuprequest->bRequestType =
769 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
770 kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND;
771 kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200);
772 kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001);
773 kingsun->speed_setuprequest->wLength =
774 cpu_to_le16(sizeof(struct ks959_speedparams));
775
776 printk(KERN_INFO "KingSun KS-959 IRDA/USB found at address %d, "
777 "Vendor: %x, Product: %x\n",
778 dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
779 le16_to_cpu(dev->descriptor.idProduct));
780
781 /* Initialize QoS for this device */
782 irda_init_max_qos_capabilies(&kingsun->qos);
783
784 /* Baud rates known to be supported. Please uncomment if devices (other
785 than a SonyEriccson K300 phone) can be shown to support higher speed
786 with this dongle.
787 */
788 kingsun->qos.baud_rate.bits =
789 IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600;
790 kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
791 irda_qos_bits_to_value(&kingsun->qos);
792
793 /* Override the network functions we need to use */
Stephen Hemminger94ffab62009-03-20 19:35:47 +0000794 net->netdev_ops = &ks959_ops;
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700795
796 ret = register_netdev(net);
797 if (ret != 0)
798 goto free_mem;
799
Greg Kroah-Hartman880c9c62008-08-18 13:21:04 -0700800 dev_info(&net->dev, "IrDA: Registered KingSun KS-959 device %s\n",
801 net->name);
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700802
803 usb_set_intfdata(intf, kingsun);
804
805 /* Situation at this point:
806 - all work buffers allocated
807 - setup requests pre-filled
808 - urbs not allocated, set to NULL
809 - max rx packet known (is KINGSUN_FIFO_SIZE)
810 - unwrap state machine (partially) initialized, but skb == NULL
811 */
812
813 return 0;
814
815 free_mem:
816 kfree(kingsun->speed_setuprequest);
817 kfree(kingsun->tx_setuprequest);
818 kfree(kingsun->tx_buf_xored);
819 kfree(kingsun->tx_buf_clear);
820 kfree(kingsun->rx_setuprequest);
821 kfree(kingsun->rx_buf);
822 free_netdev(net);
823 err_out1:
824 return ret;
825}
826
827/*
828 * The current device is removed, the USB layer tell us to shut it down...
829 */
830static void ks959_disconnect(struct usb_interface *intf)
831{
832 struct ks959_cb *kingsun = usb_get_intfdata(intf);
833
834 if (!kingsun)
835 return;
836
837 unregister_netdev(kingsun->netdev);
838
839 /* Mop up receive && transmit urb's */
840 if (kingsun->speed_urb != NULL) {
841 usb_kill_urb(kingsun->speed_urb);
842 usb_free_urb(kingsun->speed_urb);
843 kingsun->speed_urb = NULL;
844 }
845 if (kingsun->tx_urb != NULL) {
846 usb_kill_urb(kingsun->tx_urb);
847 usb_free_urb(kingsun->tx_urb);
848 kingsun->tx_urb = NULL;
849 }
850 if (kingsun->rx_urb != NULL) {
851 usb_kill_urb(kingsun->rx_urb);
852 usb_free_urb(kingsun->rx_urb);
853 kingsun->rx_urb = NULL;
854 }
855
856 kfree(kingsun->speed_setuprequest);
857 kfree(kingsun->tx_setuprequest);
858 kfree(kingsun->tx_buf_xored);
859 kfree(kingsun->tx_buf_clear);
860 kfree(kingsun->rx_setuprequest);
861 kfree(kingsun->rx_buf);
862 free_netdev(kingsun->netdev);
863
864 usb_set_intfdata(intf, NULL);
865}
866
867#ifdef CONFIG_PM
868/* USB suspend, so power off the transmitter/receiver */
869static int ks959_suspend(struct usb_interface *intf, pm_message_t message)
870{
871 struct ks959_cb *kingsun = usb_get_intfdata(intf);
872
873 netif_device_detach(kingsun->netdev);
874 if (kingsun->speed_urb != NULL)
875 usb_kill_urb(kingsun->speed_urb);
876 if (kingsun->tx_urb != NULL)
877 usb_kill_urb(kingsun->tx_urb);
878 if (kingsun->rx_urb != NULL)
879 usb_kill_urb(kingsun->rx_urb);
880 return 0;
881}
882
883/* Coming out of suspend, so reset hardware */
884static int ks959_resume(struct usb_interface *intf)
885{
886 struct ks959_cb *kingsun = usb_get_intfdata(intf);
887
888 if (kingsun->rx_urb != NULL) {
889 /* Setup request already filled in ks959_probe */
890 usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
891 }
892 netif_device_attach(kingsun->netdev);
893
894 return 0;
895}
896#endif
897
898/*
899 * USB device callbacks
900 */
901static struct usb_driver irda_driver = {
902 .name = "ks959-sir",
903 .probe = ks959_probe,
904 .disconnect = ks959_disconnect,
905 .id_table = dongles,
906#ifdef CONFIG_PM
907 .suspend = ks959_suspend,
908 .resume = ks959_resume,
909#endif
910};
911
Greg Kroah-Hartmand632eb12011-11-18 09:44:20 -0800912module_usb_driver(irda_driver);
Alex Villacís Lasso4b6aa592007-08-28 15:58:31 -0700913
914MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
915MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959");
916MODULE_LICENSE("GPL");