void pps_event(int source, struct pps_ktime *ts, int event, void *data) { struct pps_device *pps; unsigned long flags; if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) { printk(KERN_ERR "pps: unknown event (%x) for source %d\n", event, source); return; } pps = pps_get_source(source); if (!pps) return; pr_debug("PPS event on source %d at %llu.%06u\n", pps->id, (unsigned long long) ts->sec, ts->nsec); spin_lock_irqsave(&pps->lock, flags); /* Must call the echo function? */ if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR))) pps->info.echo(source, event, data); /* Check the event */ pps->current_mode = pps->params.mode; if (event & PPS_CAPTUREASSERT) { /* We have to add an offset? */ if (pps->params.mode & PPS_OFFSETASSERT) pps_add_offset(ts, &pps->params.assert_off_tu); /* Save the time stamp */ pps->assert_tu = *ts; pps->assert_sequence++; pr_debug("capture assert seq #%u for source %d\n", pps->assert_sequence, source); } if (event & PPS_CAPTURECLEAR) { /* We have to add an offset? */ if (pps->params.mode & PPS_OFFSETCLEAR) pps_add_offset(ts, &pps->params.clear_off_tu); /* Save the time stamp */ pps->clear_tu = *ts; pps->clear_sequence++; pr_debug("capture clear seq #%u for source %d\n", pps->clear_sequence, source); } pps->go = ~0; wake_up_interruptible(&pps->queue); kill_fasync(&pps->async_queue, SIGIO, POLL_IN); spin_unlock_irqrestore(&pps->lock, flags); /* Now we can release the PPS source for (possible) deregistration */ pps_put_source(pps); }
/* pps_event - register a PPS event into the system * @pps: the PPS device * @ts: the event timestamp * @event: the event type * @data: userdef pointer * * This function is used by each PPS client in order to register a new * PPS event into the system (it's usually called inside an IRQ handler). * * If an echo function is associated with the PPS device it will be called * as: * pps->info.echo(pps, event, data); */ void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event, void *data) { unsigned long flags; int captured = 0; struct pps_ktime ts_real; /* check event type */ BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0); dev_dbg(pps->dev, "PPS event at %ld.%09ld\n", ts->ts_real.tv_sec, ts->ts_real.tv_nsec); timespec_to_pps_ktime(&ts_real, ts->ts_real); spin_lock_irqsave(&pps->lock, flags); /* Must call the echo function? */ if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR))) pps->info.echo(pps, event, data); /* Check the event */ pps->current_mode = pps->params.mode; if (event & pps->params.mode & PPS_CAPTUREASSERT) { /* We have to add an offset? */ if (pps->params.mode & PPS_OFFSETASSERT) pps_add_offset(&ts_real, &pps->params.assert_off_tu); /* Save the time stamp */ pps->assert_tu = ts_real; pps->assert_sequence++; dev_dbg(pps->dev, "capture assert seq #%u\n", pps->assert_sequence); captured = ~0; } if (event & pps->params.mode & PPS_CAPTURECLEAR) { /* We have to add an offset? */ if (pps->params.mode & PPS_OFFSETCLEAR) pps_add_offset(&ts_real, &pps->params.clear_off_tu); /* Save the time stamp */ pps->clear_tu = ts_real; pps->clear_sequence++; dev_dbg(pps->dev, "capture clear seq #%u\n", pps->clear_sequence); captured = ~0; } pps_kc_event(pps, ts, event); /* Wake up if captured something */ if (captured) { pps->last_ev++; wake_up_interruptible_all(&pps->queue); kill_fasync(&pps->async_queue, SIGIO, POLL_IN); } spin_unlock_irqrestore(&pps->lock, flags); }