/*
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
#include <IOKit/hidsystem/IOHITablet.h>
#include <IOKit/hidsystem/IOHITabletPointer.h>

OSDefineMetaClassAndStructors(IOHITablet, IOHIPointing);

UInt16 IOHITablet::generateTabletID()
{
    static UInt16 _nextTabletID = 0;
    return _nextTabletID++;
}

bool IOHITablet::init(OSDictionary *propTable)
{
    if (!IOHIPointing::init(propTable)) {
        return false;
    }

    _systemTabletID = generateTabletID();
    setProperty(kIOHISystemTabletID, (unsigned long long)_systemTabletID, 16);

    return true;
}

bool IOHITablet::open(IOService *			client,
                      IOOptionBits 			options,
                      RelativePointerEventAction	rpeAction,
                      AbsolutePointerEventAction	apeAction,
                      ScrollWheelEventAction		sweAction,
                      TabletEventAction			tabletAction,
                      ProximityEventAction		proximityAction)
{
    
    if (client == this) return true;
     
    return open(client, 
                options, 
                0,
                (RelativePointerEventCallback)rpeAction, 
                (AbsolutePointerEventCallback)apeAction, 
                (ScrollWheelEventCallback)sweAction, 
                (TabletEventCallback)tabletAction, 
                (ProximityEventCallback)proximityAction);
}

bool IOHITablet::open(IOService *			client,
                      IOOptionBits			options,
                      void *				/*refcon*/,
                      RelativePointerEventCallback	rpeCallback,
                      AbsolutePointerEventCallback	apeCallback,
                      ScrollWheelEventCallback		sweCallback,
                      TabletEventCallback		tabletCallback,
                      ProximityEventCallback		proximityCallback)
{
    if (client == this) return true;

    if (!IOHIPointing::open(client, 
                            options,
                            0,
                            rpeCallback, 
                            apeCallback, 
                            sweCallback)) {
        return false;
    }

    _tabletEventTarget = client;
    _tabletEventAction = tabletCallback;
    _proximityEventTarget = client;
    _proximityEventAction = proximityCallback;

    return open(this, 
                options, 
                (RelativePointerEventAction)IOHIPointing::_relativePointerEvent, 
                (AbsolutePointerEventAction)IOHIPointing::_absolutePointerEvent, 
                (ScrollWheelEventAction)IOHIPointing::_scrollWheelEvent, 
                (TabletEventAction)_tabletEvent, 
                (ProximityEventAction)_proximityEvent);
}


void IOHITablet::dispatchTabletEvent(NXEventData *tabletEvent,
                                     AbsoluteTime ts)
{
    _tabletEvent(   _tabletEventTarget,
                    tabletEvent,
                    ts);
}

void IOHITablet::dispatchProximityEvent(NXEventData *proximityEvent,
                                        AbsoluteTime ts)
{
    _proximityEvent(_proximityEventTarget,
                    proximityEvent,
                    ts);
}

bool IOHITablet::startTabletPointer(IOHITabletPointer *pointer, OSDictionary *properties)
{
    bool result = false;

    do {
        if (!pointer)
            break;

        if (!pointer->init(properties))
            break;

        if (!pointer->attach(this))
            break;

        if (!pointer->start(this))
            break;

        result = true;
    } while (false);

    return result;
}

void IOHITablet::_tabletEvent(IOHITablet *self,
                           NXEventData *tabletData,
                           AbsoluteTime ts)
{
    TabletEventCallback teCallback;
    
    if (!(teCallback = (TabletEventCallback)self->_tabletEventAction))
        return;
        
    (*teCallback)(
                    self->_tabletEventTarget,
                    tabletData,
                    ts,
                    self,
                    0);
}

void IOHITablet::_proximityEvent(IOHITablet *self,
                              NXEventData *proximityData,
                              AbsoluteTime ts)
{
    ProximityEventCallback peCallback;
    
    if (!(peCallback = (ProximityEventCallback)self->_proximityEventAction))
        return;
        
    (*peCallback)(  
                    self->_proximityEventTarget,
                    proximityData,
                    ts,
                    self,
                    0);
}



