1 /* 2 * IPWireless 3G PCMCIA Network Driver 3 * 4 * Original code 5 * by Stephen Blackheath <stephen@blacksapphire.com>, 6 * Ben Martel <benm@symmetric.co.nz> 7 * 8 * Copyrighted as follows: 9 * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 * 11 * Various driver changes and rewrites, port to new kernels 12 * Copyright (C) 2006-2007 Jiri Kosina 13 * 14 * Misc code cleanups and updates 15 * Copyright (C) 2007 David Sterba 16 */ 17 18 #include <linux/init.h> 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/mutex.h> 22 #include <linux/ppp_defs.h> 23 #include <linux/if.h> 24 #include <linux/ppp-ioctl.h> 25 #include <linux/sched.h> 26 #include <linux/serial.h> 27 #include <linux/slab.h> 28 #include <linux/tty.h> 29 #include <linux/tty_driver.h> 30 #include <linux/tty_flip.h> 31 #include <linux/uaccess.h> 32 33 #include "tty.h" 34 #include "network.h" 35 #include "hardware.h" 36 #include "main.h" 37 38 #define IPWIRELESS_PCMCIA_START (0) 39 #define IPWIRELESS_PCMCIA_MINORS (24) 40 #define IPWIRELESS_PCMCIA_MINOR_RANGE (8) 41 42 #define TTYTYPE_MODEM (0) 43 #define TTYTYPE_MONITOR (1) 44 #define TTYTYPE_RAS_RAW (2) 45 46 struct ipw_tty { 47 int index; 48 struct ipw_hardware *hardware; 49 unsigned int channel_idx; 50 unsigned int secondary_channel_idx; 51 int tty_type; 52 struct ipw_network *network; 53 struct tty_struct *linux_tty; 54 int open_count; 55 unsigned int control_lines; 56 struct mutex ipw_tty_mutex; 57 int tx_bytes_queued; 58 int closing; 59 }; 60 61 static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS]; 62 63 static struct tty_driver *ipw_tty_driver; 64 65 static char *tty_type_name(int tty_type) 66 { 67 static char *channel_names[] = { 68 "modem", 69 "monitor", 70 "RAS-raw" 71 }; 72 73 return channel_names[tty_type]; 74 } 75 76 static void report_registering(struct ipw_tty *tty) 77 { 78 char *iftype = tty_type_name(tty->tty_type); 79 80 printk(KERN_INFO IPWIRELESS_PCCARD_NAME 81 ": registering %s device ttyIPWp%d\n", iftype, tty->index); 82 } 83 84 static void report_deregistering(struct ipw_tty *tty) 85 { 86 char *iftype = tty_type_name(tty->tty_type); 87 88 printk(KERN_INFO IPWIRELESS_PCCARD_NAME 89 ": deregistering %s device ttyIPWp%d\n", iftype, 90 tty->index); 91 } 92 93 static struct ipw_tty *get_tty(int index) 94 { 95 /* 96 * The 'ras_raw' channel is only available when 'loopback' mode 97 * is enabled. 98 * Number of minor starts with 16 (_RANGE * _RAS_RAW). 99 */ 100 if (!ipwireless_loopback && index >= 101 IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW) 102 return NULL; 103 104 return ttys[index]; 105 } 106 107 static int ipw_open(struct tty_struct *linux_tty, struct file *filp) 108 { 109 struct ipw_tty *tty = get_tty(linux_tty->index); 110 111 if (!tty) 112 return -ENODEV; 113 114 mutex_lock(&tty->ipw_tty_mutex); 115 116 if (tty->closing) { 117 mutex_unlock(&tty->ipw_tty_mutex); 118 return -ENODEV; 119 } 120 if (tty->open_count == 0) 121 tty->tx_bytes_queued = 0; 122 123 tty->open_count++; 124 125 tty->linux_tty = linux_tty; 126 linux_tty->driver_data = tty; 127 linux_tty->low_latency = 1; 128 129 if (tty->tty_type == TTYTYPE_MODEM) 130 ipwireless_ppp_open(tty->network); 131 132 mutex_unlock(&tty->ipw_tty_mutex); 133 134 return 0; 135 } 136 137 static void do_ipw_close(struct ipw_tty *tty) 138 { 139 tty->open_count--; 140 141 if (tty->open_count == 0) { 142 struct tty_struct *linux_tty = tty->linux_tty; 143 144 if (linux_tty != NULL) { 145 tty->linux_tty = NULL; 146 linux_tty->driver_data = NULL; 147 148 if (tty->tty_type == TTYTYPE_MODEM) 149 ipwireless_ppp_close(tty->network); 150 } 151 } 152 } 153 154 static void ipw_hangup(struct tty_struct *linux_tty) 155 { 156 struct ipw_tty *tty = linux_tty->driver_data; 157 158 if (!tty) 159 return; 160 161 mutex_lock(&tty->ipw_tty_mutex); 162 if (tty->open_count == 0) { 163 mutex_unlock(&tty->ipw_tty_mutex); 164 return; 165 } 166 167 do_ipw_close(tty); 168 169 mutex_unlock(&tty->ipw_tty_mutex); 170 } 171 172 static void ipw_close(struct tty_struct *linux_tty, struct file *filp) 173 { 174 ipw_hangup(linux_tty); 175 } 176 177 /* Take data received from hardware, and send it out the tty */ 178 void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, 179 unsigned int length) 180 { 181 struct tty_struct *linux_tty; 182 int work = 0; 183 184 mutex_lock(&tty->ipw_tty_mutex); 185 linux_tty = tty->linux_tty; 186 if (linux_tty == NULL) { 187 mutex_unlock(&tty->ipw_tty_mutex); 188 return; 189 } 190 191 if (!tty->open_count) { 192 mutex_unlock(&tty->ipw_tty_mutex); 193 return; 194 } 195 mutex_unlock(&tty->ipw_tty_mutex); 196 197 work = tty_insert_flip_string(linux_tty, data, length); 198 199 if (work != length) 200 printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME 201 ": %d chars not inserted to flip buffer!\n", 202 length - work); 203 204 /* 205 * This may sleep if ->low_latency is set 206 */ 207 if (work) 208 tty_flip_buffer_push(linux_tty); 209 } 210 211 static void ipw_write_packet_sent_callback(void *callback_data, 212 unsigned int packet_length) 213 { 214 struct ipw_tty *tty = callback_data; 215 216 /* 217 * Packet has been sent, so we subtract the number of bytes from our 218 * tally of outstanding TX bytes. 219 */ 220 tty->tx_bytes_queued -= packet_length; 221 } 222 223 static int ipw_write(struct tty_struct *linux_tty, 224 const unsigned char *buf, int count) 225 { 226 struct ipw_tty *tty = linux_tty->driver_data; 227 int room, ret; 228 229 if (!tty) 230 return -ENODEV; 231 232 mutex_lock(&tty->ipw_tty_mutex); 233 if (!tty->open_count) { 234 mutex_unlock(&tty->ipw_tty_mutex); 235 return -EINVAL; 236 } 237 238 room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; 239 if (room < 0) 240 room = 0; 241 /* Don't allow caller to write any more than we have room for */ 242 if (count > room) 243 count = room; 244 245 if (count == 0) { 246 mutex_unlock(&tty->ipw_tty_mutex); 247 return 0; 248 } 249 250 ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, 251 buf, count, 252 ipw_write_packet_sent_callback, tty); 253 if (ret == -1) { 254 mutex_unlock(&tty->ipw_tty_mutex); 255 return 0; 256 } 257 258 tty->tx_bytes_queued += count; 259 mutex_unlock(&tty->ipw_tty_mutex); 260 261 return count; 262 } 263 264 static int ipw_write_room(struct tty_struct *linux_tty) 265 { 266 struct ipw_tty *tty = linux_tty->driver_data; 267 int room; 268 269 /* FIXME: Exactly how is the tty object locked here .. */ 270 if (!tty) 271 return -ENODEV; 272 273 if (!tty->open_count) 274 return -EINVAL; 275 276 room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; 277 if (room < 0) 278 room = 0; 279 280 return room; 281 } 282 283 static int ipwireless_get_serial_info(struct ipw_tty *tty, 284 struct serial_struct __user *retinfo) 285 { 286 struct serial_struct tmp; 287 288 if (!retinfo) 289 return (-EFAULT); 290 291 memset(&tmp, 0, sizeof(tmp)); 292 tmp.type = PORT_UNKNOWN; 293 tmp.line = tty->index; 294 tmp.port = 0; 295 tmp.irq = 0; 296 tmp.flags = 0; 297 tmp.baud_base = 115200; 298 tmp.close_delay = 0; 299 tmp.closing_wait = 0; 300 tmp.custom_divisor = 0; 301 tmp.hub6 = 0; 302 if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) 303 return -EFAULT; 304 305 return 0; 306 } 307 308 static int ipw_chars_in_buffer(struct tty_struct *linux_tty) 309 { 310 struct ipw_tty *tty = linux_tty->driver_data; 311 312 if (!tty) 313 return 0; 314 315 if (!tty->open_count) 316 return 0; 317 318 return tty->tx_bytes_queued; 319 } 320 321 static int get_control_lines(struct ipw_tty *tty) 322 { 323 unsigned int my = tty->control_lines; 324 unsigned int out = 0; 325 326 if (my & IPW_CONTROL_LINE_RTS) 327 out |= TIOCM_RTS; 328 if (my & IPW_CONTROL_LINE_DTR) 329 out |= TIOCM_DTR; 330 if (my & IPW_CONTROL_LINE_CTS) 331 out |= TIOCM_CTS; 332 if (my & IPW_CONTROL_LINE_DSR) 333 out |= TIOCM_DSR; 334 if (my & IPW_CONTROL_LINE_DCD) 335 out |= TIOCM_CD; 336 337 return out; 338 } 339 340 static int set_control_lines(struct ipw_tty *tty, unsigned int set, 341 unsigned int clear) 342 { 343 int ret; 344 345 if (set & TIOCM_RTS) { 346 ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1); 347 if (ret) 348 return ret; 349 if (tty->secondary_channel_idx != -1) { 350 ret = ipwireless_set_RTS(tty->hardware, 351 tty->secondary_channel_idx, 1); 352 if (ret) 353 return ret; 354 } 355 } 356 if (set & TIOCM_DTR) { 357 ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1); 358 if (ret) 359 return ret; 360 if (tty->secondary_channel_idx != -1) { 361 ret = ipwireless_set_DTR(tty->hardware, 362 tty->secondary_channel_idx, 1); 363 if (ret) 364 return ret; 365 } 366 } 367 if (clear & TIOCM_RTS) { 368 ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0); 369 if (tty->secondary_channel_idx != -1) { 370 ret = ipwireless_set_RTS(tty->hardware, 371 tty->secondary_channel_idx, 0); 372 if (ret) 373 return ret; 374 } 375 } 376 if (clear & TIOCM_DTR) { 377 ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0); 378 if (tty->secondary_channel_idx != -1) { 379 ret = ipwireless_set_DTR(tty->hardware, 380 tty->secondary_channel_idx, 0); 381 if (ret) 382 return ret; 383 } 384 } 385 return 0; 386 } 387 388 static int ipw_tiocmget(struct tty_struct *linux_tty) 389 { 390 struct ipw_tty *tty = linux_tty->driver_data; 391 /* FIXME: Exactly how is the tty object locked here .. */ 392 393 if (!tty) 394 return -ENODEV; 395 396 if (!tty->open_count) 397 return -EINVAL; 398 399 return get_control_lines(tty); 400 } 401 402 static int 403 ipw_tiocmset(struct tty_struct *linux_tty, 404 unsigned int set, unsigned int clear) 405 { 406 struct ipw_tty *tty = linux_tty->driver_data; 407 /* FIXME: Exactly how is the tty object locked here .. */ 408 409 if (!tty) 410 return -ENODEV; 411 412 if (!tty->open_count) 413 return -EINVAL; 414 415 return set_control_lines(tty, set, clear); 416 } 417 418 static int ipw_ioctl(struct tty_struct *linux_tty, 419 unsigned int cmd, unsigned long arg) 420 { 421 struct ipw_tty *tty = linux_tty->driver_data; 422 423 if (!tty) 424 return -ENODEV; 425 426 if (!tty->open_count) 427 return -EINVAL; 428 429 /* FIXME: Exactly how is the tty object locked here .. */ 430 431 switch (cmd) { 432 case TIOCGSERIAL: 433 return ipwireless_get_serial_info(tty, (void __user *) arg); 434 435 case TIOCSSERIAL: 436 return 0; /* Keeps the PCMCIA scripts happy. */ 437 } 438 439 if (tty->tty_type == TTYTYPE_MODEM) { 440 switch (cmd) { 441 case PPPIOCGCHAN: 442 { 443 int chan = ipwireless_ppp_channel_index( 444 tty->network); 445 446 if (chan < 0) 447 return -ENODEV; 448 if (put_user(chan, (int __user *) arg)) 449 return -EFAULT; 450 } 451 return 0; 452 453 case PPPIOCGUNIT: 454 { 455 int unit = ipwireless_ppp_unit_number( 456 tty->network); 457 458 if (unit < 0) 459 return -ENODEV; 460 if (put_user(unit, (int __user *) arg)) 461 return -EFAULT; 462 } 463 return 0; 464 465 case FIONREAD: 466 { 467 int val = 0; 468 469 if (put_user(val, (int __user *) arg)) 470 return -EFAULT; 471 } 472 return 0; 473 case TCFLSH: 474 return tty_perform_flush(linux_tty, arg); 475 } 476 } 477 return -ENOIOCTLCMD; 478 } 479 480 static int add_tty(int j, 481 struct ipw_hardware *hardware, 482 struct ipw_network *network, int channel_idx, 483 int secondary_channel_idx, int tty_type) 484 { 485 ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL); 486 if (!ttys[j]) 487 return -ENOMEM; 488 ttys[j]->index = j; 489 ttys[j]->hardware = hardware; 490 ttys[j]->channel_idx = channel_idx; 491 ttys[j]->secondary_channel_idx = secondary_channel_idx; 492 ttys[j]->network = network; 493 ttys[j]->tty_type = tty_type; 494 mutex_init(&ttys[j]->ipw_tty_mutex); 495 496 tty_register_device(ipw_tty_driver, j, NULL); 497 ipwireless_associate_network_tty(network, channel_idx, ttys[j]); 498 499 if (secondary_channel_idx != -1) 500 ipwireless_associate_network_tty(network, 501 secondary_channel_idx, 502 ttys[j]); 503 if (get_tty(j) == ttys[j]) 504 report_registering(ttys[j]); 505 return 0; 506 } 507 508 struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware, 509 struct ipw_network *network) 510 { 511 int i, j; 512 513 for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) { 514 int allfree = 1; 515 516 for (j = i; j < IPWIRELESS_PCMCIA_MINORS; 517 j += IPWIRELESS_PCMCIA_MINOR_RANGE) 518 if (ttys[j] != NULL) { 519 allfree = 0; 520 break; 521 } 522 523 if (allfree) { 524 j = i; 525 526 if (add_tty(j, hardware, network, 527 IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS, 528 TTYTYPE_MODEM)) 529 return NULL; 530 531 j += IPWIRELESS_PCMCIA_MINOR_RANGE; 532 if (add_tty(j, hardware, network, 533 IPW_CHANNEL_DIALLER, -1, 534 TTYTYPE_MONITOR)) 535 return NULL; 536 537 j += IPWIRELESS_PCMCIA_MINOR_RANGE; 538 if (add_tty(j, hardware, network, 539 IPW_CHANNEL_RAS, -1, 540 TTYTYPE_RAS_RAW)) 541 return NULL; 542 543 return ttys[i]; 544 } 545 } 546 return NULL; 547 } 548 549 /* 550 * Must be called before ipwireless_network_free(). 551 */ 552 void ipwireless_tty_free(struct ipw_tty *tty) 553 { 554 int j; 555 struct ipw_network *network = ttys[tty->index]->network; 556 557 for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS; 558 j += IPWIRELESS_PCMCIA_MINOR_RANGE) { 559 struct ipw_tty *ttyj = ttys[j]; 560 561 if (ttyj) { 562 mutex_lock(&ttyj->ipw_tty_mutex); 563 if (get_tty(j) == ttyj) 564 report_deregistering(ttyj); 565 ttyj->closing = 1; 566 if (ttyj->linux_tty != NULL) { 567 mutex_unlock(&ttyj->ipw_tty_mutex); 568 tty_hangup(ttyj->linux_tty); 569 /* Wait till the tty_hangup has completed */ 570 flush_work_sync(&ttyj->linux_tty->hangup_work); 571 /* FIXME: Exactly how is the tty object locked here 572 against a parallel ioctl etc */ 573 mutex_lock(&ttyj->ipw_tty_mutex); 574 } 575 while (ttyj->open_count) 576 do_ipw_close(ttyj); 577 ipwireless_disassociate_network_ttys(network, 578 ttyj->channel_idx); 579 tty_unregister_device(ipw_tty_driver, j); 580 ttys[j] = NULL; 581 mutex_unlock(&ttyj->ipw_tty_mutex); 582 kfree(ttyj); 583 } 584 } 585 } 586 587 static const struct tty_operations tty_ops = { 588 .open = ipw_open, 589 .close = ipw_close, 590 .hangup = ipw_hangup, 591 .write = ipw_write, 592 .write_room = ipw_write_room, 593 .ioctl = ipw_ioctl, 594 .chars_in_buffer = ipw_chars_in_buffer, 595 .tiocmget = ipw_tiocmget, 596 .tiocmset = ipw_tiocmset, 597 }; 598 599 int ipwireless_tty_init(void) 600 { 601 int result; 602 603 ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS); 604 if (!ipw_tty_driver) 605 return -ENOMEM; 606 607 ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME; 608 ipw_tty_driver->name = "ttyIPWp"; 609 ipw_tty_driver->major = 0; 610 ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START; 611 ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; 612 ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL; 613 ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; 614 ipw_tty_driver->init_termios = tty_std_termios; 615 ipw_tty_driver->init_termios.c_cflag = 616 B9600 | CS8 | CREAD | HUPCL | CLOCAL; 617 ipw_tty_driver->init_termios.c_ispeed = 9600; 618 ipw_tty_driver->init_termios.c_ospeed = 9600; 619 tty_set_operations(ipw_tty_driver, &tty_ops); 620 result = tty_register_driver(ipw_tty_driver); 621 if (result) { 622 printk(KERN_ERR IPWIRELESS_PCCARD_NAME 623 ": failed to register tty driver\n"); 624 put_tty_driver(ipw_tty_driver); 625 return result; 626 } 627 628 return 0; 629 } 630 631 void ipwireless_tty_release(void) 632 { 633 int ret; 634 635 ret = tty_unregister_driver(ipw_tty_driver); 636 put_tty_driver(ipw_tty_driver); 637 if (ret != 0) 638 printk(KERN_ERR IPWIRELESS_PCCARD_NAME 639 ": tty_unregister_driver failed with code %d\n", ret); 640 } 641 642 int ipwireless_tty_is_modem(struct ipw_tty *tty) 643 { 644 return tty->tty_type == TTYTYPE_MODEM; 645 } 646 647 void 648 ipwireless_tty_notify_control_line_change(struct ipw_tty *tty, 649 unsigned int channel_idx, 650 unsigned int control_lines, 651 unsigned int changed_mask) 652 { 653 unsigned int old_control_lines = tty->control_lines; 654 655 tty->control_lines = (tty->control_lines & ~changed_mask) 656 | (control_lines & changed_mask); 657 658 /* 659 * If DCD is de-asserted, we close the tty so pppd can tell that we 660 * have gone offline. 661 */ 662 if ((old_control_lines & IPW_CONTROL_LINE_DCD) 663 && !(tty->control_lines & IPW_CONTROL_LINE_DCD) 664 && tty->linux_tty) { 665 tty_hangup(tty->linux_tty); 666 } 667 } 668 669