Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.6-rc2 813 lines 23 kB view raw
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/init.h> 84#include <linux/slab.h> 85#include <linux/usb.h> 86#include <linux/device.h> 87#include <linux/crc32.h> 88 89#include <asm/unaligned.h> 90#include <asm/byteorder.h> 91#include <asm/uaccess.h> 92 93#include <net/irda/irda.h> 94#include <net/irda/wrapper.h> 95#include <net/irda/crc.h> 96 97#define KSDAZZLE_VENDOR_ID 0x07d0 98#define KSDAZZLE_PRODUCT_ID 0x4100 99 100/* These are the currently known USB ids */ 101static struct usb_device_id dongles[] = { 102 /* KingSun Co,Ltd IrDA/USB Bridge */ 103 {USB_DEVICE(KSDAZZLE_VENDOR_ID, KSDAZZLE_PRODUCT_ID)}, 104 {} 105}; 106 107MODULE_DEVICE_TABLE(usb, dongles); 108 109#define KINGSUN_MTT 0x07 110#define KINGSUN_REQ_RECV 0x01 111#define KINGSUN_REQ_SEND 0x09 112 113#define KINGSUN_SND_FIFO_SIZE 2048 /* Max packet we can send */ 114#define KINGSUN_RCV_MAX 2048 /* Max transfer we can receive */ 115 116struct ksdazzle_speedparams { 117 __le32 baudrate; /* baud rate, little endian */ 118 __u8 flags; 119 __u8 reserved[3]; 120} __packed; 121 122#define KS_DATA_5_BITS 0x00 123#define KS_DATA_6_BITS 0x01 124#define KS_DATA_7_BITS 0x02 125#define KS_DATA_8_BITS 0x03 126 127#define KS_STOP_BITS_1 0x00 128#define KS_STOP_BITS_2 0x08 129 130#define KS_PAR_DISABLE 0x00 131#define KS_PAR_EVEN 0x10 132#define KS_PAR_ODD 0x30 133#define KS_RESET 0x80 134 135#define KINGSUN_EP_IN 0 136#define KINGSUN_EP_OUT 1 137 138struct ksdazzle_cb { 139 struct usb_device *usbdev; /* init: probe_irda */ 140 struct net_device *netdev; /* network layer */ 141 struct irlap_cb *irlap; /* The link layer we are binded to */ 142 143 struct qos_info qos; 144 145 struct urb *tx_urb; 146 __u8 *tx_buf_clear; 147 unsigned int tx_buf_clear_used; 148 unsigned int tx_buf_clear_sent; 149 __u8 tx_payload[8]; 150 151 struct urb *rx_urb; 152 __u8 *rx_buf; 153 iobuff_t rx_unwrap_buff; 154 155 struct usb_ctrlrequest *speed_setuprequest; 156 struct urb *speed_urb; 157 struct ksdazzle_speedparams speedparams; 158 unsigned int new_speed; 159 160 __u8 ep_in; 161 __u8 ep_out; 162 163 spinlock_t lock; 164 int receiving; 165}; 166 167/* Callback transmission routine */ 168static void ksdazzle_speed_irq(struct urb *urb) 169{ 170 /* unlink, shutdown, unplug, other nasties */ 171 if (urb->status != 0) 172 dev_err(&urb->dev->dev, 173 "ksdazzle_speed_irq: urb asynchronously failed - %d\n", 174 urb->status); 175} 176 177/* Send a control request to change speed of the dongle */ 178static int ksdazzle_change_speed(struct ksdazzle_cb *kingsun, unsigned speed) 179{ 180 static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400, 181 57600, 115200, 576000, 1152000, 4000000, 0 182 }; 183 int err; 184 unsigned int i; 185 186 if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL) 187 return -ENOMEM; 188 189 /* Check that requested speed is among the supported ones */ 190 for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ; 191 if (supported_speeds[i] == 0) 192 return -EOPNOTSUPP; 193 194 memset(&(kingsun->speedparams), 0, sizeof(struct ksdazzle_speedparams)); 195 kingsun->speedparams.baudrate = cpu_to_le32(speed); 196 kingsun->speedparams.flags = KS_DATA_8_BITS; 197 198 /* speed_setuprequest pre-filled in ksdazzle_probe */ 199 usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev, 200 usb_sndctrlpipe(kingsun->usbdev, 0), 201 (unsigned char *)kingsun->speed_setuprequest, 202 &(kingsun->speedparams), 203 sizeof(struct ksdazzle_speedparams), 204 ksdazzle_speed_irq, kingsun); 205 kingsun->speed_urb->status = 0; 206 err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC); 207 208 return err; 209} 210 211/* Submit one fragment of an IrDA frame to the dongle */ 212static void ksdazzle_send_irq(struct urb *urb); 213static int ksdazzle_submit_tx_fragment(struct ksdazzle_cb *kingsun) 214{ 215 unsigned int wraplen; 216 int ret; 217 218 /* We can send at most 7 bytes of payload at a time */ 219 wraplen = 7; 220 if (wraplen > kingsun->tx_buf_clear_used) 221 wraplen = kingsun->tx_buf_clear_used; 222 223 /* Prepare payload prefix with used length */ 224 memset(kingsun->tx_payload, 0, 8); 225 kingsun->tx_payload[0] = (unsigned char)0xf8 + wraplen; 226 memcpy(kingsun->tx_payload + 1, kingsun->tx_buf_clear, wraplen); 227 228 usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev, 229 usb_sndintpipe(kingsun->usbdev, kingsun->ep_out), 230 kingsun->tx_payload, 8, ksdazzle_send_irq, kingsun, 1); 231 kingsun->tx_urb->status = 0; 232 ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC); 233 234 /* Remember how much data was sent, in order to update at callback */ 235 kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0; 236 return ret; 237} 238 239/* Callback transmission routine */ 240static void ksdazzle_send_irq(struct urb *urb) 241{ 242 struct ksdazzle_cb *kingsun = urb->context; 243 struct net_device *netdev = kingsun->netdev; 244 int ret = 0; 245 246 /* in process of stopping, just drop data */ 247 if (!netif_running(kingsun->netdev)) { 248 dev_err(&kingsun->usbdev->dev, 249 "ksdazzle_send_irq: Network not running!\n"); 250 return; 251 } 252 253 /* unlink, shutdown, unplug, other nasties */ 254 if (urb->status != 0) { 255 dev_err(&kingsun->usbdev->dev, 256 "ksdazzle_send_irq: urb asynchronously failed - %d\n", 257 urb->status); 258 return; 259 } 260 261 if (kingsun->tx_buf_clear_used > 0) { 262 /* Update data remaining to be sent */ 263 if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) { 264 memmove(kingsun->tx_buf_clear, 265 kingsun->tx_buf_clear + 266 kingsun->tx_buf_clear_sent, 267 kingsun->tx_buf_clear_used - 268 kingsun->tx_buf_clear_sent); 269 } 270 kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent; 271 kingsun->tx_buf_clear_sent = 0; 272 273 if (kingsun->tx_buf_clear_used > 0) { 274 /* There is more data to be sent */ 275 if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { 276 dev_err(&kingsun->usbdev->dev, 277 "ksdazzle_send_irq: failed tx_urb submit: %d\n", 278 ret); 279 switch (ret) { 280 case -ENODEV: 281 case -EPIPE: 282 break; 283 default: 284 netdev->stats.tx_errors++; 285 netif_start_queue(netdev); 286 } 287 } 288 } else { 289 /* All data sent, send next speed && wake network queue */ 290 if (kingsun->new_speed != -1 && 291 cpu_to_le32(kingsun->new_speed) != 292 kingsun->speedparams.baudrate) 293 ksdazzle_change_speed(kingsun, 294 kingsun->new_speed); 295 296 netif_wake_queue(netdev); 297 } 298 } 299} 300 301/* 302 * Called from net/core when new frame is available. 303 */ 304static netdev_tx_t ksdazzle_hard_xmit(struct sk_buff *skb, 305 struct net_device *netdev) 306{ 307 struct ksdazzle_cb *kingsun; 308 unsigned int wraplen; 309 int ret = 0; 310 311 netif_stop_queue(netdev); 312 313 /* the IRDA wrapping routines don't deal with non linear skb */ 314 SKB_LINEAR_ASSERT(skb); 315 316 kingsun = netdev_priv(netdev); 317 318 spin_lock(&kingsun->lock); 319 kingsun->new_speed = irda_get_next_speed(skb); 320 321 /* Append data to the end of whatever data remains to be transmitted */ 322 wraplen = 323 async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE); 324 kingsun->tx_buf_clear_used = wraplen; 325 326 if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { 327 dev_err(&kingsun->usbdev->dev, 328 "ksdazzle_hard_xmit: failed tx_urb submit: %d\n", ret); 329 switch (ret) { 330 case -ENODEV: 331 case -EPIPE: 332 break; 333 default: 334 netdev->stats.tx_errors++; 335 netif_start_queue(netdev); 336 } 337 } else { 338 netdev->stats.tx_packets++; 339 netdev->stats.tx_bytes += skb->len; 340 341 } 342 343 dev_kfree_skb(skb); 344 spin_unlock(&kingsun->lock); 345 346 return NETDEV_TX_OK; 347} 348 349/* Receive callback function */ 350static void ksdazzle_rcv_irq(struct urb *urb) 351{ 352 struct ksdazzle_cb *kingsun = urb->context; 353 struct net_device *netdev = kingsun->netdev; 354 355 /* in process of stopping, just drop data */ 356 if (!netif_running(netdev)) { 357 kingsun->receiving = 0; 358 return; 359 } 360 361 /* unlink, shutdown, unplug, other nasties */ 362 if (urb->status != 0) { 363 dev_err(&kingsun->usbdev->dev, 364 "ksdazzle_rcv_irq: urb asynchronously failed - %d\n", 365 urb->status); 366 kingsun->receiving = 0; 367 return; 368 } 369 370 if (urb->actual_length > 0) { 371 __u8 *bytes = urb->transfer_buffer; 372 unsigned int i; 373 374 for (i = 0; i < urb->actual_length; i++) { 375 async_unwrap_char(netdev, &netdev->stats, 376 &kingsun->rx_unwrap_buff, bytes[i]); 377 } 378 kingsun->receiving = 379 (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0; 380 } 381 382 /* This urb has already been filled in ksdazzle_net_open. It is assumed that 383 urb keeps the pointer to the payload buffer. 384 */ 385 urb->status = 0; 386 usb_submit_urb(urb, GFP_ATOMIC); 387} 388 389/* 390 * Function ksdazzle_net_open (dev) 391 * 392 * Network device is taken up. Usually this is done by "ifconfig irda0 up" 393 */ 394static int ksdazzle_net_open(struct net_device *netdev) 395{ 396 struct ksdazzle_cb *kingsun = netdev_priv(netdev); 397 int err = -ENOMEM; 398 char hwname[16]; 399 400 /* At this point, urbs are NULL, and skb is NULL (see ksdazzle_probe) */ 401 kingsun->receiving = 0; 402 403 /* Initialize for SIR to copy data directly into skb. */ 404 kingsun->rx_unwrap_buff.in_frame = FALSE; 405 kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; 406 kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU; 407 kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); 408 if (!kingsun->rx_unwrap_buff.skb) 409 goto free_mem; 410 411 skb_reserve(kingsun->rx_unwrap_buff.skb, 1); 412 kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data; 413 414 kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); 415 if (!kingsun->rx_urb) 416 goto free_mem; 417 418 kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); 419 if (!kingsun->tx_urb) 420 goto free_mem; 421 422 kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL); 423 if (!kingsun->speed_urb) 424 goto free_mem; 425 426 /* Initialize speed for dongle */ 427 kingsun->new_speed = 9600; 428 err = ksdazzle_change_speed(kingsun, 9600); 429 if (err < 0) 430 goto free_mem; 431 432 /* 433 * Now that everything should be initialized properly, 434 * Open new IrLAP layer instance to take care of us... 435 */ 436 sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); 437 kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); 438 if (!kingsun->irlap) { 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");