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