1/***************************************************************************** 2* 3* Filename: ksdazzle.c 4* Version: 0.1.2 5* Description: Irda KingSun Dazzle USB Dongle 6* Status: Experimental 7* Author: Alex Villacís Lasso <a_villacis@palosanto.com> 8* 9* Based on stir4200, mcs7780, kingsun-sir drivers. 10* 11* This program is free software; you can redistribute it and/or modify 12* it under the terms of the GNU General Public License as published by 13* the Free Software Foundation; either version 2 of the License. 14* 15* This program is distributed in the hope that it will be useful, 16* but WITHOUT ANY WARRANTY; without even the implied warranty of 17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18* GNU General Public License for more details. 19* 20* You should have received a copy of the GNU General Public License 21* along with this program; if not, write to the Free Software 22* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23* 24*****************************************************************************/ 25 26/* 27 * Following is my most current (2007-07-26) understanding of how the Kingsun 28 * 07D0:4100 dongle (sometimes known as the MA-660) is supposed to work. This 29 * information was deduced by examining the USB traffic captured with USBSnoopy 30 * from the WinXP driver. Feel free to update here as more of the dongle is 31 * known. 32 * 33 * General: This dongle exposes one interface with two interrupt endpoints, one 34 * IN and one OUT. In this regard, it is similar to what the Kingsun/Donshine 35 * dongle (07c0:4200) exposes. Traffic is raw and needs to be wrapped and 36 * unwrapped manually as in stir4200, kingsun-sir, and ks959-sir. 37 * 38 * Transmission: To transmit an IrDA frame, it is necessary to wrap it, then 39 * split it into multiple segments of up to 7 bytes each, and transmit each in 40 * sequence. It seems that sending a single big block (like kingsun-sir does) 41 * won't work with this dongle. Each segment needs to be prefixed with a value 42 * equal to (unsigned char)0xF8 + <number of bytes in segment>, inside a payload 43 * of exactly 8 bytes. For example, a segment of 1 byte gets prefixed by 0xF9, 44 * and one of 7 bytes gets prefixed by 0xFF. The bytes at the end of the 45 * payload, not considered by the prefix, are ignored (set to 0 by this 46 * implementation). 47 * 48 * Reception: To receive data, the driver must poll the dongle regularly (like 49 * kingsun-sir.c) with interrupt URBs. If data is available, it will be returned 50 * in payloads from 0 to 8 bytes long. When concatenated, these payloads form 51 * a raw IrDA stream that needs to be unwrapped as in stir4200 and kingsun-sir 52 * 53 * Speed change: To change the speed of the dongle, the driver prepares a 54 * control URB with the following as a setup packet: 55 * bRequestType USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE 56 * bRequest 0x09 57 * wValue 0x0200 58 * wIndex 0x0001 59 * wLength 0x0008 (length of the payload) 60 * The payload is a 8-byte record, apparently identical to the one used in 61 * drivers/usb/serial/cypress_m8.c to change speed: 62 * __u32 baudSpeed; 63 * unsigned int dataBits : 2; // 0 - 5 bits 3 - 8 bits 64 * unsigned int : 1; 65 * unsigned int stopBits : 1; 66 * unsigned int parityEnable : 1; 67 * unsigned int parityType : 1; 68 * unsigned int : 1; 69 * unsigned int reset : 1; 70 * unsigned char reserved[3]; // set to 0 71 * 72 * For now only SIR speeds have been observed with this dongle. Therefore, 73 * nothing is known on what changes (if any) must be done to frame wrapping / 74 * unwrapping for higher than SIR speeds. This driver assumes no change is 75 * necessary and announces support for all the way to 115200 bps. 76 */ 77 78#include <linux/module.h> 79#include <linux/moduleparam.h> 80#include <linux/kernel.h> 81#include <linux/types.h> 82#include <linux/errno.h> 83#include <linux/slab.h> 84#include <linux/usb.h> 85#include <linux/device.h> 86#include <linux/crc32.h> 87 88#include <asm/unaligned.h> 89#include <asm/byteorder.h> 90#include <asm/uaccess.h> 91 92#include <net/irda/irda.h> 93#include <net/irda/wrapper.h> 94#include <net/irda/crc.h> 95 96#define KSDAZZLE_VENDOR_ID 0x07d0 97#define KSDAZZLE_PRODUCT_ID 0x4100 98 99/* These are the currently known USB ids */ 100static struct usb_device_id dongles[] = { 101 /* KingSun Co,Ltd IrDA/USB Bridge */ 102 {USB_DEVICE(KSDAZZLE_VENDOR_ID, KSDAZZLE_PRODUCT_ID)}, 103 {} 104}; 105 106MODULE_DEVICE_TABLE(usb, dongles); 107 108#define KINGSUN_MTT 0x07 109#define KINGSUN_REQ_RECV 0x01 110#define KINGSUN_REQ_SEND 0x09 111 112#define KINGSUN_SND_FIFO_SIZE 2048 /* Max packet we can send */ 113#define KINGSUN_RCV_MAX 2048 /* Max transfer we can receive */ 114 115struct ksdazzle_speedparams { 116 __le32 baudrate; /* baud rate, little endian */ 117 __u8 flags; 118 __u8 reserved[3]; 119} __packed; 120 121#define KS_DATA_5_BITS 0x00 122#define KS_DATA_6_BITS 0x01 123#define KS_DATA_7_BITS 0x02 124#define KS_DATA_8_BITS 0x03 125 126#define KS_STOP_BITS_1 0x00 127#define KS_STOP_BITS_2 0x08 128 129#define KS_PAR_DISABLE 0x00 130#define KS_PAR_EVEN 0x10 131#define KS_PAR_ODD 0x30 132#define KS_RESET 0x80 133 134#define KINGSUN_EP_IN 0 135#define KINGSUN_EP_OUT 1 136 137struct ksdazzle_cb { 138 struct usb_device *usbdev; /* init: probe_irda */ 139 struct net_device *netdev; /* network layer */ 140 struct irlap_cb *irlap; /* The link layer we are binded to */ 141 142 struct qos_info qos; 143 144 struct urb *tx_urb; 145 __u8 *tx_buf_clear; 146 unsigned int tx_buf_clear_used; 147 unsigned int tx_buf_clear_sent; 148 __u8 tx_payload[8]; 149 150 struct urb *rx_urb; 151 __u8 *rx_buf; 152 iobuff_t rx_unwrap_buff; 153 154 struct usb_ctrlrequest *speed_setuprequest; 155 struct urb *speed_urb; 156 struct ksdazzle_speedparams speedparams; 157 unsigned int new_speed; 158 159 __u8 ep_in; 160 __u8 ep_out; 161 162 spinlock_t lock; 163 int receiving; 164}; 165 166/* Callback transmission routine */ 167static void ksdazzle_speed_irq(struct urb *urb) 168{ 169 /* unlink, shutdown, unplug, other nasties */ 170 if (urb->status != 0) 171 dev_err(&urb->dev->dev, 172 "ksdazzle_speed_irq: urb asynchronously failed - %d\n", 173 urb->status); 174} 175 176/* Send a control request to change speed of the dongle */ 177static int ksdazzle_change_speed(struct ksdazzle_cb *kingsun, unsigned speed) 178{ 179 static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400, 180 57600, 115200, 576000, 1152000, 4000000, 0 181 }; 182 int err; 183 unsigned int i; 184 185 if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL) 186 return -ENOMEM; 187 188 /* Check that requested speed is among the supported ones */ 189 for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ; 190 if (supported_speeds[i] == 0) 191 return -EOPNOTSUPP; 192 193 memset(&(kingsun->speedparams), 0, sizeof(struct ksdazzle_speedparams)); 194 kingsun->speedparams.baudrate = cpu_to_le32(speed); 195 kingsun->speedparams.flags = KS_DATA_8_BITS; 196 197 /* speed_setuprequest pre-filled in ksdazzle_probe */ 198 usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev, 199 usb_sndctrlpipe(kingsun->usbdev, 0), 200 (unsigned char *)kingsun->speed_setuprequest, 201 &(kingsun->speedparams), 202 sizeof(struct ksdazzle_speedparams), 203 ksdazzle_speed_irq, kingsun); 204 kingsun->speed_urb->status = 0; 205 err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC); 206 207 return err; 208} 209 210/* Submit one fragment of an IrDA frame to the dongle */ 211static void ksdazzle_send_irq(struct urb *urb); 212static int ksdazzle_submit_tx_fragment(struct ksdazzle_cb *kingsun) 213{ 214 unsigned int wraplen; 215 int ret; 216 217 /* We can send at most 7 bytes of payload at a time */ 218 wraplen = 7; 219 if (wraplen > kingsun->tx_buf_clear_used) 220 wraplen = kingsun->tx_buf_clear_used; 221 222 /* Prepare payload prefix with used length */ 223 memset(kingsun->tx_payload, 0, 8); 224 kingsun->tx_payload[0] = (unsigned char)0xf8 + wraplen; 225 memcpy(kingsun->tx_payload + 1, kingsun->tx_buf_clear, wraplen); 226 227 usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev, 228 usb_sndintpipe(kingsun->usbdev, kingsun->ep_out), 229 kingsun->tx_payload, 8, ksdazzle_send_irq, kingsun, 1); 230 kingsun->tx_urb->status = 0; 231 ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC); 232 233 /* Remember how much data was sent, in order to update at callback */ 234 kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0; 235 return ret; 236} 237 238/* Callback transmission routine */ 239static void ksdazzle_send_irq(struct urb *urb) 240{ 241 struct ksdazzle_cb *kingsun = urb->context; 242 struct net_device *netdev = kingsun->netdev; 243 int ret = 0; 244 245 /* in process of stopping, just drop data */ 246 if (!netif_running(kingsun->netdev)) { 247 dev_err(&kingsun->usbdev->dev, 248 "ksdazzle_send_irq: Network not running!\n"); 249 return; 250 } 251 252 /* unlink, shutdown, unplug, other nasties */ 253 if (urb->status != 0) { 254 dev_err(&kingsun->usbdev->dev, 255 "ksdazzle_send_irq: urb asynchronously failed - %d\n", 256 urb->status); 257 return; 258 } 259 260 if (kingsun->tx_buf_clear_used > 0) { 261 /* Update data remaining to be sent */ 262 if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) { 263 memmove(kingsun->tx_buf_clear, 264 kingsun->tx_buf_clear + 265 kingsun->tx_buf_clear_sent, 266 kingsun->tx_buf_clear_used - 267 kingsun->tx_buf_clear_sent); 268 } 269 kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent; 270 kingsun->tx_buf_clear_sent = 0; 271 272 if (kingsun->tx_buf_clear_used > 0) { 273 /* There is more data to be sent */ 274 if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { 275 dev_err(&kingsun->usbdev->dev, 276 "ksdazzle_send_irq: failed tx_urb submit: %d\n", 277 ret); 278 switch (ret) { 279 case -ENODEV: 280 case -EPIPE: 281 break; 282 default: 283 netdev->stats.tx_errors++; 284 netif_start_queue(netdev); 285 } 286 } 287 } else { 288 /* All data sent, send next speed && wake network queue */ 289 if (kingsun->new_speed != -1 && 290 cpu_to_le32(kingsun->new_speed) != 291 kingsun->speedparams.baudrate) 292 ksdazzle_change_speed(kingsun, 293 kingsun->new_speed); 294 295 netif_wake_queue(netdev); 296 } 297 } 298} 299 300/* 301 * Called from net/core when new frame is available. 302 */ 303static netdev_tx_t ksdazzle_hard_xmit(struct sk_buff *skb, 304 struct net_device *netdev) 305{ 306 struct ksdazzle_cb *kingsun; 307 unsigned int wraplen; 308 int ret = 0; 309 310 netif_stop_queue(netdev); 311 312 /* the IRDA wrapping routines don't deal with non linear skb */ 313 SKB_LINEAR_ASSERT(skb); 314 315 kingsun = netdev_priv(netdev); 316 317 spin_lock(&kingsun->lock); 318 kingsun->new_speed = irda_get_next_speed(skb); 319 320 /* Append data to the end of whatever data remains to be transmitted */ 321 wraplen = 322 async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE); 323 kingsun->tx_buf_clear_used = wraplen; 324 325 if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { 326 dev_err(&kingsun->usbdev->dev, 327 "ksdazzle_hard_xmit: failed tx_urb submit: %d\n", ret); 328 switch (ret) { 329 case -ENODEV: 330 case -EPIPE: 331 break; 332 default: 333 netdev->stats.tx_errors++; 334 netif_start_queue(netdev); 335 } 336 } else { 337 netdev->stats.tx_packets++; 338 netdev->stats.tx_bytes += skb->len; 339 340 } 341 342 dev_kfree_skb(skb); 343 spin_unlock(&kingsun->lock); 344 345 return NETDEV_TX_OK; 346} 347 348/* Receive callback function */ 349static void ksdazzle_rcv_irq(struct urb *urb) 350{ 351 struct ksdazzle_cb *kingsun = urb->context; 352 struct net_device *netdev = kingsun->netdev; 353 354 /* in process of stopping, just drop data */ 355 if (!netif_running(netdev)) { 356 kingsun->receiving = 0; 357 return; 358 } 359 360 /* unlink, shutdown, unplug, other nasties */ 361 if (urb->status != 0) { 362 dev_err(&kingsun->usbdev->dev, 363 "ksdazzle_rcv_irq: urb asynchronously failed - %d\n", 364 urb->status); 365 kingsun->receiving = 0; 366 return; 367 } 368 369 if (urb->actual_length > 0) { 370 __u8 *bytes = urb->transfer_buffer; 371 unsigned int i; 372 373 for (i = 0; i < urb->actual_length; i++) { 374 async_unwrap_char(netdev, &netdev->stats, 375 &kingsun->rx_unwrap_buff, bytes[i]); 376 } 377 kingsun->receiving = 378 (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0; 379 } 380 381 /* This urb has already been filled in ksdazzle_net_open. It is assumed that 382 urb keeps the pointer to the payload buffer. 383 */ 384 urb->status = 0; 385 usb_submit_urb(urb, GFP_ATOMIC); 386} 387 388/* 389 * Function ksdazzle_net_open (dev) 390 * 391 * Network device is taken up. Usually this is done by "ifconfig irda0 up" 392 */ 393static int ksdazzle_net_open(struct net_device *netdev) 394{ 395 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 396 int err = -ENOMEM; 397 char hwname[16]; 398 399 /* At this point, urbs are NULL, and skb is NULL (see ksdazzle_probe) */ 400 kingsun->receiving = 0; 401 402 /* Initialize for SIR to copy data directly into skb. */ 403 kingsun->rx_unwrap_buff.in_frame = FALSE; 404 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 405 kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU; 406 kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); 407 if (!kingsun->rx_unwrap_buff.skb) 408 goto free_mem; 409 410 skb_reserve(kingsun->rx_unwrap_buff.skb, 1); 411 kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data; 412 413 kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); 414 if (!kingsun->rx_urb) 415 goto free_mem; 416 417 kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); 418 if (!kingsun->tx_urb) 419 goto free_mem; 420 421 kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL); 422 if (!kingsun->speed_urb) 423 goto free_mem; 424 425 /* Initialize speed for dongle */ 426 kingsun->new_speed = 9600; 427 err = ksdazzle_change_speed(kingsun, 9600); 428 if (err < 0) 429 goto free_mem; 430 431 /* 432 * Now that everything should be initialized properly, 433 * Open new IrLAP layer instance to take care of us... 434 */ 435 sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); 436 kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); 437 if (!kingsun->irlap) { 438 err = -ENOMEM; 439 dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); 440 goto free_mem; 441 } 442 443 /* Start reception. */ 444 usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev, 445 usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in), 446 kingsun->rx_buf, KINGSUN_RCV_MAX, ksdazzle_rcv_irq, 447 kingsun, 1); 448 kingsun->rx_urb->status = 0; 449 err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 450 if (err) { 451 dev_err(&kingsun->usbdev->dev, "first urb-submit failed: %d\n", err); 452 goto close_irlap; 453 } 454 455 netif_start_queue(netdev); 456 457 /* Situation at this point: 458 - all work buffers allocated 459 - urbs allocated and ready to fill 460 - max rx packet known (in max_rx) 461 - unwrap state machine initialized, in state outside of any frame 462 - receive request in progress 463 - IrLAP layer started, about to hand over packets to send 464 */ 465 466 return 0; 467 468 close_irlap: 469 irlap_close(kingsun->irlap); 470 free_mem: 471 usb_free_urb(kingsun->speed_urb); 472 kingsun->speed_urb = NULL; 473 usb_free_urb(kingsun->tx_urb); 474 kingsun->tx_urb = NULL; 475 usb_free_urb(kingsun->rx_urb); 476 kingsun->rx_urb = NULL; 477 if (kingsun->rx_unwrap_buff.skb) { 478 kfree_skb(kingsun->rx_unwrap_buff.skb); 479 kingsun->rx_unwrap_buff.skb = NULL; 480 kingsun->rx_unwrap_buff.head = NULL; 481 } 482 return err; 483} 484 485/* 486 * Function ksdazzle_net_close (dev) 487 * 488 * Network device is taken down. Usually this is done by 489 * "ifconfig irda0 down" 490 */ 491static int ksdazzle_net_close(struct net_device *netdev) 492{ 493 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 494 495 /* Stop transmit processing */ 496 netif_stop_queue(netdev); 497 498 /* Mop up receive && transmit urb's */ 499 usb_kill_urb(kingsun->tx_urb); 500 usb_free_urb(kingsun->tx_urb); 501 kingsun->tx_urb = NULL; 502 503 usb_kill_urb(kingsun->speed_urb); 504 usb_free_urb(kingsun->speed_urb); 505 kingsun->speed_urb = NULL; 506 507 usb_kill_urb(kingsun->rx_urb); 508 usb_free_urb(kingsun->rx_urb); 509 kingsun->rx_urb = NULL; 510 511 kfree_skb(kingsun->rx_unwrap_buff.skb); 512 kingsun->rx_unwrap_buff.skb = NULL; 513 kingsun->rx_unwrap_buff.head = NULL; 514 kingsun->rx_unwrap_buff.in_frame = FALSE; 515 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 516 kingsun->receiving = 0; 517 518 /* Stop and remove instance of IrLAP */ 519 irlap_close(kingsun->irlap); 520 521 kingsun->irlap = NULL; 522 523 return 0; 524} 525 526/* 527 * IOCTLs : Extra out-of-band network commands... 528 */ 529static int ksdazzle_net_ioctl(struct net_device *netdev, struct ifreq *rq, 530 int cmd) 531{ 532 struct if_irda_req *irq = (struct if_irda_req *)rq; 533 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 534 int ret = 0; 535 536 switch (cmd) { 537 case SIOCSBANDWIDTH: /* Set bandwidth */ 538 if (!capable(CAP_NET_ADMIN)) 539 return -EPERM; 540 541 /* Check if the device is still there */ 542 if (netif_device_present(kingsun->netdev)) 543 return ksdazzle_change_speed(kingsun, 544 irq->ifr_baudrate); 545 break; 546 547 case SIOCSMEDIABUSY: /* Set media busy */ 548 if (!capable(CAP_NET_ADMIN)) 549 return -EPERM; 550 551 /* Check if the IrDA stack is still there */ 552 if (netif_running(kingsun->netdev)) 553 irda_device_set_media_busy(kingsun->netdev, TRUE); 554 break; 555 556 case SIOCGRECEIVING: 557 /* Only approximately true */ 558 irq->ifr_receiving = kingsun->receiving; 559 break; 560 561 default: 562 ret = -EOPNOTSUPP; 563 } 564 565 return ret; 566} 567 568static const struct net_device_ops ksdazzle_ops = { 569 .ndo_start_xmit = ksdazzle_hard_xmit, 570 .ndo_open = ksdazzle_net_open, 571 .ndo_stop = ksdazzle_net_close, 572 .ndo_do_ioctl = ksdazzle_net_ioctl, 573}; 574 575/* 576 * This routine is called by the USB subsystem for each new device 577 * in the system. We need to check if the device is ours, and in 578 * this case start handling it. 579 */ 580static int ksdazzle_probe(struct usb_interface *intf, 581 const struct usb_device_id *id) 582{ 583 struct usb_host_interface *interface; 584 struct usb_endpoint_descriptor *endpoint; 585 586 struct usb_device *dev = interface_to_usbdev(intf); 587 struct ksdazzle_cb *kingsun = NULL; 588 struct net_device *net = NULL; 589 int ret = -ENOMEM; 590 int pipe, maxp_in, maxp_out; 591 __u8 ep_in; 592 __u8 ep_out; 593 594 /* Check that there really are two interrupt endpoints. Check based on the 595 one in drivers/usb/input/usbmouse.c 596 */ 597 interface = intf->cur_altsetting; 598 if (interface->desc.bNumEndpoints != 2) { 599 dev_err(&intf->dev, "ksdazzle: expected 2 endpoints, found %d\n", 600 interface->desc.bNumEndpoints); 601 return -ENODEV; 602 } 603 endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; 604 if (!usb_endpoint_is_int_in(endpoint)) { 605 dev_err(&intf->dev, 606 "ksdazzle: endpoint 0 is not interrupt IN\n"); 607 return -ENODEV; 608 } 609 610 ep_in = endpoint->bEndpointAddress; 611 pipe = usb_rcvintpipe(dev, ep_in); 612 maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 613 if (maxp_in > 255 || maxp_in <= 1) { 614 dev_err(&intf->dev, 615 "ksdazzle: endpoint 0 has max packet size %d not in range [2..255]\n", 616 maxp_in); 617 return -ENODEV; 618 } 619 620 endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; 621 if (!usb_endpoint_is_int_out(endpoint)) { 622 dev_err(&intf->dev, 623 "ksdazzle: endpoint 1 is not interrupt OUT\n"); 624 return -ENODEV; 625 } 626 627 ep_out = endpoint->bEndpointAddress; 628 pipe = usb_sndintpipe(dev, ep_out); 629 maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 630 631 /* Allocate network device container. */ 632 net = alloc_irdadev(sizeof(*kingsun)); 633 if (!net) 634 goto err_out1; 635 636 SET_NETDEV_DEV(net, &intf->dev); 637 kingsun = netdev_priv(net); 638 kingsun->netdev = net; 639 kingsun->usbdev = dev; 640 kingsun->ep_in = ep_in; 641 kingsun->ep_out = ep_out; 642 kingsun->irlap = NULL; 643 kingsun->tx_urb = NULL; 644 kingsun->tx_buf_clear = NULL; 645 kingsun->tx_buf_clear_used = 0; 646 kingsun->tx_buf_clear_sent = 0; 647 648 kingsun->rx_urb = NULL; 649 kingsun->rx_buf = NULL; 650 kingsun->rx_unwrap_buff.in_frame = FALSE; 651 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 652 kingsun->rx_unwrap_buff.skb = NULL; 653 kingsun->receiving = 0; 654 spin_lock_init(&kingsun->lock); 655 656 kingsun->speed_setuprequest = NULL; 657 kingsun->speed_urb = NULL; 658 kingsun->speedparams.baudrate = 0; 659 660 /* Allocate input buffer */ 661 kingsun->rx_buf = kmalloc(KINGSUN_RCV_MAX, GFP_KERNEL); 662 if (!kingsun->rx_buf) 663 goto free_mem; 664 665 /* Allocate output buffer */ 666 kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL); 667 if (!kingsun->tx_buf_clear) 668 goto free_mem; 669 670 /* Allocate and initialize speed setup packet */ 671 kingsun->speed_setuprequest = 672 kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); 673 if (!kingsun->speed_setuprequest) 674 goto free_mem; 675 kingsun->speed_setuprequest->bRequestType = 676 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; 677 kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND; 678 kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200); 679 kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001); 680 kingsun->speed_setuprequest->wLength = 681 cpu_to_le16(sizeof(struct ksdazzle_speedparams)); 682 683 printk(KERN_INFO "KingSun/Dazzle IRDA/USB found at address %d, " 684 "Vendor: %x, Product: %x\n", 685 dev->devnum, le16_to_cpu(dev->descriptor.idVendor), 686 le16_to_cpu(dev->descriptor.idProduct)); 687 688 /* Initialize QoS for this device */ 689 irda_init_max_qos_capabilies(&kingsun->qos); 690 691 /* Baud rates known to be supported. Please uncomment if devices (other 692 than a SonyEriccson K300 phone) can be shown to support higher speeds 693 with this dongle. 694 */ 695 kingsun->qos.baud_rate.bits = 696 IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200; 697 kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; 698 irda_qos_bits_to_value(&kingsun->qos); 699 700 /* Override the network functions we need to use */ 701 net->netdev_ops = &ksdazzle_ops; 702 703 ret = register_netdev(net); 704 if (ret != 0) 705 goto free_mem; 706 707 dev_info(&net->dev, "IrDA: Registered KingSun/Dazzle device %s\n", 708 net->name); 709 710 usb_set_intfdata(intf, kingsun); 711 712 /* Situation at this point: 713 - all work buffers allocated 714 - setup requests pre-filled 715 - urbs not allocated, set to NULL 716 - max rx packet known (is KINGSUN_FIFO_SIZE) 717 - unwrap state machine (partially) initialized, but skb == NULL 718 */ 719 720 return 0; 721 722 free_mem: 723 kfree(kingsun->speed_setuprequest); 724 kfree(kingsun->tx_buf_clear); 725 kfree(kingsun->rx_buf); 726 free_netdev(net); 727 err_out1: 728 return ret; 729} 730 731/* 732 * The current device is removed, the USB layer tell us to shut it down... 733 */ 734static void ksdazzle_disconnect(struct usb_interface *intf) 735{ 736 struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); 737 738 if (!kingsun) 739 return; 740 741 unregister_netdev(kingsun->netdev); 742 743 /* Mop up receive && transmit urb's */ 744 usb_kill_urb(kingsun->speed_urb); 745 usb_free_urb(kingsun->speed_urb); 746 kingsun->speed_urb = NULL; 747 748 usb_kill_urb(kingsun->tx_urb); 749 usb_free_urb(kingsun->tx_urb); 750 kingsun->tx_urb = NULL; 751 752 usb_kill_urb(kingsun->rx_urb); 753 usb_free_urb(kingsun->rx_urb); 754 kingsun->rx_urb = NULL; 755 756 kfree(kingsun->speed_setuprequest); 757 kfree(kingsun->tx_buf_clear); 758 kfree(kingsun->rx_buf); 759 free_netdev(kingsun->netdev); 760 761 usb_set_intfdata(intf, NULL); 762} 763 764#ifdef CONFIG_PM 765/* USB suspend, so power off the transmitter/receiver */ 766static int ksdazzle_suspend(struct usb_interface *intf, pm_message_t message) 767{ 768 struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); 769 770 netif_device_detach(kingsun->netdev); 771 if (kingsun->speed_urb != NULL) 772 usb_kill_urb(kingsun->speed_urb); 773 if (kingsun->tx_urb != NULL) 774 usb_kill_urb(kingsun->tx_urb); 775 if (kingsun->rx_urb != NULL) 776 usb_kill_urb(kingsun->rx_urb); 777 return 0; 778} 779 780/* Coming out of suspend, so reset hardware */ 781static int ksdazzle_resume(struct usb_interface *intf) 782{ 783 struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); 784 785 if (kingsun->rx_urb != NULL) { 786 /* Setup request already filled in ksdazzle_probe */ 787 usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 788 } 789 netif_device_attach(kingsun->netdev); 790 791 return 0; 792} 793#endif 794 795/* 796 * USB device callbacks 797 */ 798static struct usb_driver irda_driver = { 799 .name = "ksdazzle-sir", 800 .probe = ksdazzle_probe, 801 .disconnect = ksdazzle_disconnect, 802 .id_table = dongles, 803#ifdef CONFIG_PM 804 .suspend = ksdazzle_suspend, 805 .resume = ksdazzle_resume, 806#endif 807}; 808 809module_usb_driver(irda_driver); 810 811MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>"); 812MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun Dazzle"); 813MODULE_LICENSE("GPL"); 814