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