linux/drivers/isdn/gigaset/ser-gigaset.c
<<
>>
Prefs
   1/* This is the serial hardware link layer (HLL) for the Gigaset 307x isdn
   2 * DECT base (aka Sinus 45 isdn) using the RS232 DECT data module M101,
   3 * written as a line discipline.
   4 *
   5 * =====================================================================
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation; either version 2 of
   9 * the License, or (at your option) any later version.
  10 * =====================================================================
  11 */
  12
  13#include "gigaset.h"
  14
  15#include <linux/module.h>
  16#include <linux/moduleparam.h>
  17#include <linux/platform_device.h>
  18#include <linux/tty.h>
  19#include <linux/completion.h>
  20
  21/* Version Information */
  22#define DRIVER_AUTHOR "Tilman Schmidt"
  23#define DRIVER_DESC "Serial Driver for Gigaset 307x using Siemens M101"
  24
  25#define GIGASET_MINORS     1
  26#define GIGASET_MINOR      0
  27#define GIGASET_MODULENAME "ser_gigaset"
  28#define GIGASET_DEVNAME    "ttyGS"
  29
  30/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
  31#define IF_WRITEBUF 264
  32
  33MODULE_AUTHOR(DRIVER_AUTHOR);
  34MODULE_DESCRIPTION(DRIVER_DESC);
  35MODULE_LICENSE("GPL");
  36MODULE_ALIAS_LDISC(N_GIGASET_M101);
  37
  38static int startmode = SM_ISDN;
  39module_param(startmode, int, S_IRUGO);
  40MODULE_PARM_DESC(startmode, "initial operation mode");
  41static int cidmode = 1;
  42module_param(cidmode, int, S_IRUGO);
  43MODULE_PARM_DESC(cidmode, "stay in CID mode when idle");
  44
  45static struct gigaset_driver *driver;
  46
  47struct ser_cardstate {
  48        struct platform_device  dev;
  49        struct tty_struct       *tty;
  50        atomic_t                refcnt;
  51        struct completion       dead_cmp;
  52};
  53
  54static struct platform_driver device_driver = {
  55        .driver = {
  56                .name = GIGASET_MODULENAME,
  57        },
  58};
  59
  60static void flush_send_queue(struct cardstate *);
  61
  62/* transmit data from current open skb
  63 * result: number of bytes sent or error code < 0
  64 */
  65static int write_modem(struct cardstate *cs)
  66{
  67        struct tty_struct *tty = cs->hw.ser->tty;
  68        struct bc_state *bcs = &cs->bcs[0];     /* only one channel */
  69        struct sk_buff *skb = bcs->tx_skb;
  70        int sent = -EOPNOTSUPP;
  71
  72        if (!tty || !tty->driver || !skb)
  73                return -EINVAL;
  74
  75        if (!skb->len) {
  76                dev_kfree_skb_any(skb);
  77                bcs->tx_skb = NULL;
  78                return -EINVAL;
  79        }
  80
  81        set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
  82        if (tty->ops->write)
  83                sent = tty->ops->write(tty, skb->data, skb->len);
  84        gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent);
  85        if (sent < 0) {
  86                /* error */
  87                flush_send_queue(cs);
  88                return sent;
  89        }
  90        skb_pull(skb, sent);
  91        if (!skb->len) {
  92                /* skb sent completely */
  93                gigaset_skb_sent(bcs, skb);
  94
  95                gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
  96                        (unsigned long) skb);
  97                dev_kfree_skb_any(skb);
  98                bcs->tx_skb = NULL;
  99        }
 100        return sent;
 101}
 102
 103/*
 104 * transmit first queued command buffer
 105 * result: number of bytes sent or error code < 0
 106 */
 107static int send_cb(struct cardstate *cs)
 108{
 109        struct tty_struct *tty = cs->hw.ser->tty;
 110        struct cmdbuf_t *cb, *tcb;
 111        unsigned long flags;
 112        int sent = 0;
 113
 114        if (!tty || !tty->driver)
 115                return -EFAULT;
 116
 117        cb = cs->cmdbuf;
 118        if (!cb)
 119                return 0;       /* nothing to do */
 120
 121        if (cb->len) {
 122                set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 123                sent = tty->ops->write(tty, cb->buf + cb->offset, cb->len);
 124                if (sent < 0) {
 125                        /* error */
 126                        gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent);
 127                        flush_send_queue(cs);
 128                        return sent;
 129                }
 130                cb->offset += sent;
 131                cb->len -= sent;
 132                gig_dbg(DEBUG_OUTPUT, "send_cb: sent %d, left %u, queued %u",
 133                        sent, cb->len, cs->cmdbytes);
 134        }
 135
 136        while (cb && !cb->len) {
 137                spin_lock_irqsave(&cs->cmdlock, flags);
 138                cs->cmdbytes -= cs->curlen;
 139                tcb = cb;
 140                cs->cmdbuf = cb = cb->next;
 141                if (cb) {
 142                        cb->prev = NULL;
 143                        cs->curlen = cb->len;
 144                } else {
 145                        cs->lastcmdbuf = NULL;
 146                        cs->curlen = 0;
 147                }
 148                spin_unlock_irqrestore(&cs->cmdlock, flags);
 149
 150                if (tcb->wake_tasklet)
 151                        tasklet_schedule(tcb->wake_tasklet);
 152                kfree(tcb);
 153        }
 154        return sent;
 155}
 156
 157/*
 158 * send queue tasklet
 159 * If there is already a skb opened, put data to the transfer buffer
 160 * by calling "write_modem".
 161 * Otherwise take a new skb out of the queue.
 162 */
 163static void gigaset_modem_fill(unsigned long data)
 164{
 165        struct cardstate *cs = (struct cardstate *) data;
 166        struct bc_state *bcs;
 167        int sent = 0;
 168
 169        if (!cs || !(bcs = cs->bcs)) {
 170                gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__);
 171                return;
 172        }
 173        if (!bcs->tx_skb) {
 174                /* no skb is being sent; send command if any */
 175                sent = send_cb(cs);
 176                gig_dbg(DEBUG_OUTPUT, "%s: send_cb -> %d", __func__, sent);
 177                if (sent)
 178                        /* something sent or error */
 179                        return;
 180
 181                /* no command to send; get skb */
 182                if (!(bcs->tx_skb = skb_dequeue(&bcs->squeue)))
 183                        /* no skb either, nothing to do */
 184                        return;
 185
 186                gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)",
 187                        (unsigned long) bcs->tx_skb);
 188        }
 189
 190        /* send skb */
 191        gig_dbg(DEBUG_OUTPUT, "%s: tx_skb", __func__);
 192        if (write_modem(cs) < 0)
 193                gig_dbg(DEBUG_OUTPUT, "%s: write_modem failed", __func__);
 194}
 195
 196/*
 197 * throw away all data queued for sending
 198 */
 199static void flush_send_queue(struct cardstate *cs)
 200{
 201        struct sk_buff *skb;
 202        struct cmdbuf_t *cb;
 203        unsigned long flags;
 204
 205        /* command queue */
 206        spin_lock_irqsave(&cs->cmdlock, flags);
 207        while ((cb = cs->cmdbuf) != NULL) {
 208                cs->cmdbuf = cb->next;
 209                if (cb->wake_tasklet)
 210                        tasklet_schedule(cb->wake_tasklet);
 211                kfree(cb);
 212        }
 213        cs->cmdbuf = cs->lastcmdbuf = NULL;
 214        cs->cmdbytes = cs->curlen = 0;
 215        spin_unlock_irqrestore(&cs->cmdlock, flags);
 216
 217        /* data queue */
 218        if (cs->bcs->tx_skb)
 219                dev_kfree_skb_any(cs->bcs->tx_skb);
 220        while ((skb = skb_dequeue(&cs->bcs->squeue)) != NULL)
 221                dev_kfree_skb_any(skb);
 222}
 223
 224
 225/* Gigaset Driver Interface */
 226/* ======================== */
 227
 228/*
 229 * queue an AT command string for transmission to the Gigaset device
 230 * parameters:
 231 *      cs              controller state structure
 232 *      buf             buffer containing the string to send
 233 *      len             number of characters to send
 234 *      wake_tasklet    tasklet to run when transmission is complete, or NULL
 235 * return value:
 236 *      number of bytes queued, or error code < 0
 237 */
 238static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
 239                             int len, struct tasklet_struct *wake_tasklet)
 240{
 241        struct cmdbuf_t *cb;
 242        unsigned long flags;
 243
 244        gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
 245                             DEBUG_TRANSCMD : DEBUG_LOCKCMD,
 246                           "CMD Transmit", len, buf);
 247
 248        if (len <= 0)
 249                return 0;
 250
 251        if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
 252                dev_err(cs->dev, "%s: out of memory!\n", __func__);
 253                return -ENOMEM;
 254        }
 255
 256        memcpy(cb->buf, buf, len);
 257        cb->len = len;
 258        cb->offset = 0;
 259        cb->next = NULL;
 260        cb->wake_tasklet = wake_tasklet;
 261
 262        spin_lock_irqsave(&cs->cmdlock, flags);
 263        cb->prev = cs->lastcmdbuf;
 264        if (cs->lastcmdbuf)
 265                cs->lastcmdbuf->next = cb;
 266        else {
 267                cs->cmdbuf = cb;
 268                cs->curlen = len;
 269        }
 270        cs->cmdbytes += len;
 271        cs->lastcmdbuf = cb;
 272        spin_unlock_irqrestore(&cs->cmdlock, flags);
 273
 274        spin_lock_irqsave(&cs->lock, flags);
 275        if (cs->connected)
 276                tasklet_schedule(&cs->write_tasklet);
 277        spin_unlock_irqrestore(&cs->lock, flags);
 278        return len;
 279}
 280
 281/*
 282 * tty_driver.write_room interface routine
 283 * return number of characters the driver will accept to be written
 284 * parameter:
 285 *      controller state structure
 286 * return value:
 287 *      number of characters
 288 */
 289static int gigaset_write_room(struct cardstate *cs)
 290{
 291        unsigned bytes;
 292
 293        bytes = cs->cmdbytes;
 294        return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0;
 295}
 296
 297/*
 298 * tty_driver.chars_in_buffer interface routine
 299 * return number of characters waiting to be sent
 300 * parameter:
 301 *      controller state structure
 302 * return value:
 303 *      number of characters
 304 */
 305static int gigaset_chars_in_buffer(struct cardstate *cs)
 306{
 307        return cs->cmdbytes;
 308}
 309
 310/*
 311 * implementation of ioctl(GIGASET_BRKCHARS)
 312 * parameter:
 313 *      controller state structure
 314 * return value:
 315 *      -EINVAL (unimplemented function)
 316 */
 317static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
 318{
 319        /* not implemented */
 320        return -EINVAL;
 321}
 322
 323/*
 324 * Open B channel
 325 * Called by "do_action" in ev-layer.c
 326 */
 327static int gigaset_init_bchannel(struct bc_state *bcs)
 328{
 329        /* nothing to do for M10x */
 330        gigaset_bchannel_up(bcs);
 331        return 0;
 332}
 333
 334/*
 335 * Close B channel
 336 * Called by "do_action" in ev-layer.c
 337 */
 338static int gigaset_close_bchannel(struct bc_state *bcs)
 339{
 340        /* nothing to do for M10x */
 341        gigaset_bchannel_down(bcs);
 342        return 0;
 343}
 344
 345/*
 346 * Set up B channel structure
 347 * This is called by "gigaset_initcs" in common.c
 348 */
 349static int gigaset_initbcshw(struct bc_state *bcs)
 350{
 351        /* unused */
 352        bcs->hw.ser = NULL;
 353        return 1;
 354}
 355
 356/*
 357 * Free B channel structure
 358 * Called by "gigaset_freebcs" in common.c
 359 */
 360static int gigaset_freebcshw(struct bc_state *bcs)
 361{
 362        /* unused */
 363        return 1;
 364}
 365
 366/*
 367 * Reinitialize B channel structure
 368 * This is called by "bcs_reinit" in common.c
 369 */
 370static void gigaset_reinitbcshw(struct bc_state *bcs)
 371{
 372        /* nothing to do for M10x */
 373}
 374
 375/*
 376 * Free hardware specific device data
 377 * This will be called by "gigaset_freecs" in common.c
 378 */
 379static void gigaset_freecshw(struct cardstate *cs)
 380{
 381        tasklet_kill(&cs->write_tasklet);
 382        if (!cs->hw.ser)
 383                return;
 384        dev_set_drvdata(&cs->hw.ser->dev.dev, NULL);
 385        platform_device_unregister(&cs->hw.ser->dev);
 386        kfree(cs->hw.ser);
 387        cs->hw.ser = NULL;
 388}
 389
 390static void gigaset_device_release(struct device *dev)
 391{
 392        struct platform_device *pdev = to_platform_device(dev);
 393
 394        /* adapted from platform_device_release() in drivers/base/platform.c */
 395        //FIXME is this actually necessary?
 396        kfree(dev->platform_data);
 397        kfree(pdev->resource);
 398}
 399
 400/*
 401 * Set up hardware specific device data
 402 * This is called by "gigaset_initcs" in common.c
 403 */
 404static int gigaset_initcshw(struct cardstate *cs)
 405{
 406        int rc;
 407
 408        if (!(cs->hw.ser = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL))) {
 409                pr_err("out of memory\n");
 410                return 0;
 411        }
 412
 413        cs->hw.ser->dev.name = GIGASET_MODULENAME;
 414        cs->hw.ser->dev.id = cs->minor_index;
 415        cs->hw.ser->dev.dev.release = gigaset_device_release;
 416        if ((rc = platform_device_register(&cs->hw.ser->dev)) != 0) {
 417                pr_err("error %d registering platform device\n", rc);
 418                kfree(cs->hw.ser);
 419                cs->hw.ser = NULL;
 420                return 0;
 421        }
 422        dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
 423
 424        tasklet_init(&cs->write_tasklet,
 425                     &gigaset_modem_fill, (unsigned long) cs);
 426        return 1;
 427}
 428
 429/*
 430 * set modem control lines
 431 * Parameters:
 432 *      card state structure
 433 *      modem control line state ([TIOCM_DTR]|[TIOCM_RTS])
 434 * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c
 435 * and by "if_lock" and "if_termios" in interface.c
 436 */
 437static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state)
 438{
 439        struct tty_struct *tty = cs->hw.ser->tty;
 440        unsigned int set, clear;
 441
 442        if (!tty || !tty->driver || !tty->ops->tiocmset)
 443                return -EINVAL;
 444        set = new_state & ~old_state;
 445        clear = old_state & ~new_state;
 446        if (!set && !clear)
 447                return 0;
 448        gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
 449        return tty->ops->tiocmset(tty, NULL, set, clear);
 450}
 451
 452static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
 453{
 454        return -EINVAL;
 455}
 456
 457static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
 458{
 459        return -EINVAL;
 460}
 461
 462static const struct gigaset_ops ops = {
 463        gigaset_write_cmd,
 464        gigaset_write_room,
 465        gigaset_chars_in_buffer,
 466        gigaset_brkchars,
 467        gigaset_init_bchannel,
 468        gigaset_close_bchannel,
 469        gigaset_initbcshw,
 470        gigaset_freebcshw,
 471        gigaset_reinitbcshw,
 472        gigaset_initcshw,
 473        gigaset_freecshw,
 474        gigaset_set_modem_ctrl,
 475        gigaset_baud_rate,
 476        gigaset_set_line_ctrl,
 477        gigaset_m10x_send_skb,  /* asyncdata.c */
 478        gigaset_m10x_input,     /* asyncdata.c */
 479};
 480
 481
 482/* Line Discipline Interface */
 483/* ========================= */
 484
 485/* helper functions for cardstate refcounting */
 486static struct cardstate *cs_get(struct tty_struct *tty)
 487{
 488        struct cardstate *cs = tty->disc_data;
 489
 490        if (!cs || !cs->hw.ser) {
 491                gig_dbg(DEBUG_ANY, "%s: no cardstate", __func__);
 492                return NULL;
 493        }
 494        atomic_inc(&cs->hw.ser->refcnt);
 495        return cs;
 496}
 497
 498static void cs_put(struct cardstate *cs)
 499{
 500        if (atomic_dec_and_test(&cs->hw.ser->refcnt))
 501                complete(&cs->hw.ser->dead_cmp);
 502}
 503
 504/*
 505 * Called by the tty driver when the line discipline is pushed onto the tty.
 506 * Called in process context.
 507 */
 508static int
 509gigaset_tty_open(struct tty_struct *tty)
 510{
 511        struct cardstate *cs;
 512
 513        gig_dbg(DEBUG_INIT, "Starting HLL for Gigaset M101");
 514
 515        pr_info(DRIVER_DESC "\n");
 516
 517        if (!driver) {
 518                pr_err("%s: no driver structure\n", __func__);
 519                return -ENODEV;
 520        }
 521
 522        /* allocate memory for our device state and intialize it */
 523        if (!(cs = gigaset_initcs(driver, 1, 1, 0, cidmode,
 524                                  GIGASET_MODULENAME)))
 525                goto error;
 526
 527        cs->dev = &cs->hw.ser->dev.dev;
 528        cs->hw.ser->tty = tty;
 529        atomic_set(&cs->hw.ser->refcnt, 1);
 530        init_completion(&cs->hw.ser->dead_cmp);
 531
 532        tty->disc_data = cs;
 533
 534        /* OK.. Initialization of the datastructures and the HW is done.. Now
 535         * startup system and notify the LL that we are ready to run
 536         */
 537        if (startmode == SM_LOCKED)
 538                cs->mstate = MS_LOCKED;
 539        if (!gigaset_start(cs)) {
 540                tasklet_kill(&cs->write_tasklet);
 541                goto error;
 542        }
 543
 544        gig_dbg(DEBUG_INIT, "Startup of HLL done");
 545        return 0;
 546
 547error:
 548        gig_dbg(DEBUG_INIT, "Startup of HLL failed");
 549        tty->disc_data = NULL;
 550        gigaset_freecs(cs);
 551        return -ENODEV;
 552}
 553
 554/*
 555 * Called by the tty driver when the line discipline is removed.
 556 * Called from process context.
 557 */
 558static void
 559gigaset_tty_close(struct tty_struct *tty)
 560{
 561        struct cardstate *cs = tty->disc_data;
 562
 563        gig_dbg(DEBUG_INIT, "Stopping HLL for Gigaset M101");
 564
 565        if (!cs) {
 566                gig_dbg(DEBUG_INIT, "%s: no cardstate", __func__);
 567                return;
 568        }
 569
 570        /* prevent other callers from entering ldisc methods */
 571        tty->disc_data = NULL;
 572
 573        if (!cs->hw.ser)
 574                pr_err("%s: no hw cardstate\n", __func__);
 575        else {
 576                /* wait for running methods to finish */
 577                if (!atomic_dec_and_test(&cs->hw.ser->refcnt))
 578                        wait_for_completion(&cs->hw.ser->dead_cmp);
 579        }
 580
 581        /* stop operations */
 582        gigaset_stop(cs);
 583        tasklet_kill(&cs->write_tasklet);
 584        flush_send_queue(cs);
 585        cs->dev = NULL;
 586        gigaset_freecs(cs);
 587
 588        gig_dbg(DEBUG_INIT, "Shutdown of HLL done");
 589}
 590
 591/*
 592 * Called by the tty driver when the tty line is hung up.
 593 * Wait for I/O to driver to complete and unregister ISDN device.
 594 * This is already done by the close routine, so just call that.
 595 * Called from process context.
 596 */
 597static int gigaset_tty_hangup(struct tty_struct *tty)
 598{
 599        gigaset_tty_close(tty);
 600        return 0;
 601}
 602
 603/*
 604 * Read on the tty.
 605 * Unused, received data goes only to the Gigaset driver.
 606 */
 607static ssize_t
 608gigaset_tty_read(struct tty_struct *tty, struct file *file,
 609                 unsigned char __user *buf, size_t count)
 610{
 611        return -EAGAIN;
 612}
 613
 614/*
 615 * Write on the tty.
 616 * Unused, transmit data comes only from the Gigaset driver.
 617 */
 618static ssize_t
 619gigaset_tty_write(struct tty_struct *tty, struct file *file,
 620                  const unsigned char *buf, size_t count)
 621{
 622        return -EAGAIN;
 623}
 624
 625/*
 626 * Ioctl on the tty.
 627 * Called in process context only.
 628 * May be re-entered by multiple ioctl calling threads.
 629 */
 630static int
 631gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
 632                  unsigned int cmd, unsigned long arg)
 633{
 634        struct cardstate *cs = cs_get(tty);
 635        int rc, val;
 636        int __user *p = (int __user *)arg;
 637
 638        if (!cs)
 639                return -ENXIO;
 640
 641        switch (cmd) {
 642
 643        case FIONREAD:
 644                /* unused, always return zero */
 645                val = 0;
 646                rc = put_user(val, p);
 647                break;
 648
 649        case TCFLSH:
 650                /* flush our buffers and the serial port's buffer */
 651                switch (arg) {
 652                case TCIFLUSH:
 653                        /* no own input buffer to flush */
 654                        break;
 655                case TCIOFLUSH:
 656                case TCOFLUSH:
 657                        flush_send_queue(cs);
 658                        break;
 659                }
 660                /* Pass through */
 661
 662        default:
 663                /* pass through to underlying serial device */
 664                rc = n_tty_ioctl_helper(tty, file, cmd, arg);
 665                break;
 666        }
 667        cs_put(cs);
 668        return rc;
 669}
 670
 671/*
 672 * Called by the tty driver when a block of data has been received.
 673 * Will not be re-entered while running but other ldisc functions
 674 * may be called in parallel.
 675 * Can be called from hard interrupt level as well as soft interrupt
 676 * level or mainline.
 677 * Parameters:
 678 *      tty     tty structure
 679 *      buf     buffer containing received characters
 680 *      cflags  buffer containing error flags for received characters (ignored)
 681 *      count   number of received characters
 682 */
 683static void
 684gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
 685                    char *cflags, int count)
 686{
 687        struct cardstate *cs = cs_get(tty);
 688        unsigned tail, head, n;
 689        struct inbuf_t *inbuf;
 690
 691        if (!cs)
 692                return;
 693        if (!(inbuf = cs->inbuf)) {
 694                dev_err(cs->dev, "%s: no inbuf\n", __func__);
 695                cs_put(cs);
 696                return;
 697        }
 698
 699        tail = inbuf->tail;
 700        head = inbuf->head;
 701        gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes",
 702                head, tail, count);
 703
 704        if (head <= tail) {
 705                /* possible buffer wraparound */
 706                n = min_t(unsigned, count, RBUFSIZE - tail);
 707                memcpy(inbuf->data + tail, buf, n);
 708                tail = (tail + n) % RBUFSIZE;
 709                buf += n;
 710                count -= n;
 711        }
 712
 713        if (count > 0) {
 714                /* tail < head and some data left */
 715                n = head - tail - 1;
 716                if (count > n) {
 717                        dev_err(cs->dev,
 718                                "inbuf overflow, discarding %d bytes\n",
 719                                count - n);
 720                        count = n;
 721                }
 722                memcpy(inbuf->data + tail, buf, count);
 723                tail += count;
 724        }
 725
 726        gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
 727        inbuf->tail = tail;
 728
 729        /* Everything was received .. Push data into handler */
 730        gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
 731        gigaset_schedule_event(cs);
 732        cs_put(cs);
 733}
 734
 735/*
 736 * Called by the tty driver when there's room for more data to send.
 737 */
 738static void
 739gigaset_tty_wakeup(struct tty_struct *tty)
 740{
 741        struct cardstate *cs = cs_get(tty);
 742
 743        clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 744        if (!cs)
 745                return;
 746        tasklet_schedule(&cs->write_tasklet);
 747        cs_put(cs);
 748}
 749
 750static struct tty_ldisc_ops gigaset_ldisc = {
 751        .owner          = THIS_MODULE,
 752        .magic          = TTY_LDISC_MAGIC,
 753        .name           = "ser_gigaset",
 754        .open           = gigaset_tty_open,
 755        .close          = gigaset_tty_close,
 756        .hangup         = gigaset_tty_hangup,
 757        .read           = gigaset_tty_read,
 758        .write          = gigaset_tty_write,
 759        .ioctl          = gigaset_tty_ioctl,
 760        .receive_buf    = gigaset_tty_receive,
 761        .write_wakeup   = gigaset_tty_wakeup,
 762};
 763
 764
 765/* Initialization / Shutdown */
 766/* ========================= */
 767
 768static int __init ser_gigaset_init(void)
 769{
 770        int rc;
 771
 772        gig_dbg(DEBUG_INIT, "%s", __func__);
 773        if ((rc = platform_driver_register(&device_driver)) != 0) {
 774                pr_err("error %d registering platform driver\n", rc);
 775                return rc;
 776        }
 777
 778        /* allocate memory for our driver state and intialize it */
 779        if (!(driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
 780                                          GIGASET_MODULENAME, GIGASET_DEVNAME,
 781                                          &ops, THIS_MODULE)))
 782                goto error;
 783
 784        if ((rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc)) != 0) {
 785                pr_err("error %d registering line discipline\n", rc);
 786                goto error;
 787        }
 788
 789        return 0;
 790
 791error:
 792        if (driver) {
 793                gigaset_freedriver(driver);
 794                driver = NULL;
 795        }
 796        platform_driver_unregister(&device_driver);
 797        return rc;
 798}
 799
 800static void __exit ser_gigaset_exit(void)
 801{
 802        int rc;
 803
 804        gig_dbg(DEBUG_INIT, "%s", __func__);
 805
 806        if (driver) {
 807                gigaset_freedriver(driver);
 808                driver = NULL;
 809        }
 810
 811        if ((rc = tty_unregister_ldisc(N_GIGASET_M101)) != 0)
 812                pr_err("error %d unregistering line discipline\n", rc);
 813
 814        platform_driver_unregister(&device_driver);
 815}
 816
 817module_init(ser_gigaset_init);
 818module_exit(ser_gigaset_exit);
 819
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.