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