unimotion.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1.  /*
  2.  *  UniMotion - Unified Motion detection for Apple portables.
  3.  *
  4.  *  Copyright (c) 2006 Lincoln Ramsay. All rights reserved.
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Lesser General Public
  8.  *  License version 2.1 as published by the Free Software Foundation.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Lesser General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Lesser General Public
  16.  *  License along with this library; if not, write to the Free Software
  17.  *  Foundation Inc. 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
  18.  */
  19. /*
  20.  * HISTORY of Motion
  21.  * Written by Christian Klein
  22.  * Modified for iBook compatibility by Pall Thayer
  23.  * Modified for Hi Res Powerbook compatibility by Pall Thayer
  24.  * Modified for MacBook Pro compatibility by Randy Green
  25.  * Disparate forks unified into UniMotion by Lincoln Ramsay
  26.  */
  27. // This license applies to the portions created by Cristian Klein.
  28. /* motion.c
  29.  *
  30.  * a little program to display the coords returned by
  31.  * the powerbook motion sensor
  32.  *
  33.  * A fine piece of c0de, brought to you by
  34.  *
  35.  *               ---===---
  36.  * *** teenage mutant ninja hero coders ***
  37.  *               ---===---
  38.  *
  39.  * All of the software included is copyrighted by Christian Klein <chris@5711.org>.
  40.  *
  41.  * Copyright 2005 Christian Klein. All rights reserved.
  42.  *
  43.  * Redistribution and use in source and binary forms, with or without
  44.  * modification, are permitted provided that the following conditions
  45.  * are met:
  46.  * 1. Redistributions of source code must retain the above copyright
  47.  *    notice, this list of conditions and the following disclaimer.
  48.  * 2. Redistributions in binary form must reproduce the above copyright
  49.  *    notice, this list of conditions and the following disclaimer in the
  50.  *    documentation and/or other materials provided with the distribution.
  51.  * 3. The name of the author must not be used to endorse or promote
  52.  *    products derived from this software
  53.  *    without specific prior written permission.
  54.  *
  55.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  56.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  57.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  58.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  59.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  60.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  61.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  62.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  63.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  64.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  65.  * SUCH DAMAGE.
  66.  *
  67.  */
  68. #ifdef __APPLE__
  69. #include "unimotion.h"
  70. #include <IOKit/IOKitLib.h>
  71. #include <CoreFoundation/CoreFoundation.h>
  72. #include <stdint.h>
  73. enum data_type {
  74.     PB_IB,
  75.     MBP
  76. };
  77. struct pb_ib_data {
  78.     int8_t x;
  79.     int8_t y;
  80.     int8_t z;
  81.     int8_t pad[57];
  82. };
  83. struct mbp_data {
  84.     int16_t x;
  85.     int16_t y;
  86.     int16_t z;
  87.     int8_t pad[34];
  88. };
  89. union motion_data {
  90.     struct pb_ib_data pb_ib;
  91.     struct mbp_data mbp;
  92. };
  93. static int set_values(int type, int *kernFunc, char **servMatch, int *dataType)
  94. {
  95.     switch ( type ) {
  96.         case powerbook:
  97.             *kernFunc = 21;
  98.             *servMatch = "IOI2CMotionSensor";
  99.             *dataType = PB_IB;
  100.             break;
  101.         case ibook:
  102.             *kernFunc = 21;
  103.             *servMatch = "IOI2CMotionSensor";
  104.             *dataType = PB_IB;
  105.             break;
  106.         case highrespb:
  107.             *kernFunc = 21;
  108.             *servMatch = "PMUMotionSensor";
  109.             *dataType = PB_IB;
  110.             break;
  111.         case macbookpro:
  112.             *kernFunc = 5;
  113.             *servMatch = "SMCMotionSensor";
  114.             *dataType = MBP;
  115.             break;
  116.         default:
  117.             return 0;
  118.     }
  119.     return 1;
  120. }
  121. static int probe_sms(int kernFunc, char *servMatch, int dataType, void *data)
  122. {
  123.     kern_return_t result;
  124.     mach_port_t masterPort;
  125.     io_iterator_t iterator;
  126.     io_object_t aDevice;
  127.     io_connect_t  dataPort;
  128.     size_t structureInputSize;
  129.     size_t structureOutputSize;
  130.     union motion_data inputStructure;
  131.     union motion_data *outputStructure;
  132.     outputStructure = (union motion_data *)data;
  133.     result = IOMasterPort(MACH_PORT_NULL, &masterPort);
  134.     CFMutableDictionaryRef matchingDictionary = IOServiceMatching(servMatch);
  135.     result = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator);
  136.     if (result != KERN_SUCCESS) {
  137.         //fputs("IOServiceGetMatchingServices returned error.n", stderr);
  138.         return 0;
  139.     }
  140.     aDevice = IOIteratorNext(iterator);
  141.     IOObjectRelease(iterator);
  142.     if (aDevice == 0) {
  143.         //fputs("No motion sensor availablen", stderr);
  144.         return 0;
  145.     }
  146.     result = IOServiceOpen(aDevice, mach_task_self(), 0, &dataPort);
  147.     IOObjectRelease(aDevice);
  148.     if (result != KERN_SUCCESS) {
  149.         //fputs("Could not open motion sensor devicen", stderr);
  150.         return 0;
  151.     }
  152.     switch ( dataType ) {
  153.         case PB_IB:
  154.             structureInputSize = sizeof(struct pb_ib_data);
  155.             structureOutputSize = sizeof(struct pb_ib_data);
  156.             break;
  157.         case MBP:
  158.             structureInputSize = sizeof(struct mbp_data);
  159.             structureOutputSize = sizeof(struct mbp_data);
  160.             break;
  161.         default:
  162.             return 0;
  163.     }
  164.     memset(&inputStructure, 0, sizeof(union motion_data));
  165.     memset(outputStructure, 0, sizeof(union motion_data));
  166.     result = IOConnectCallStructMethod(dataPort, kernFunc, &inputStructure, 
  167.                 structureInputSize, outputStructure, &structureOutputSize );
  168.     IOServiceClose(dataPort);
  169.     if (result != KERN_SUCCESS) {
  170.         //puts("no coords");
  171.         return 0;
  172.     }
  173.     return 1;
  174. }
  175. int detect_sms()
  176. {
  177.     int kernFunc;
  178.     char *servMatch;
  179.     int dataType;
  180.     union motion_data data;
  181.     int i;
  182.     for ( i = 1; ; i++ ) {
  183.         if ( !set_values(i, &kernFunc, &servMatch, &dataType) )
  184.             break;
  185.         if ( probe_sms(kernFunc, servMatch, dataType, &data) )
  186.             return i;
  187.     }
  188.     return unknown;
  189. }
  190. int read_sms_raw(int type, int *x, int *y, int *z)
  191. {
  192.     int kernFunc;
  193.     char *servMatch;
  194.     int dataType;
  195.     union motion_data data;
  196.     if ( !set_values(type, &kernFunc, &servMatch, &dataType) )
  197.         return 0;
  198.     if ( probe_sms(kernFunc, servMatch, dataType, &data) ) {
  199.         switch ( dataType ) {
  200.             case PB_IB:
  201.                 if ( x ) *x = data.pb_ib.x;
  202.                 if ( y ) *y = data.pb_ib.y;
  203.                 if ( z ) *z = data.pb_ib.z;
  204.                 break;
  205.             case MBP:
  206.                 if ( x ) *x = data.mbp.x;
  207.                 if ( y ) *y = data.mbp.y;
  208.                 if ( z ) *z = data.mbp.z;
  209.                 break;
  210.             default:
  211.                 return 0;
  212.         }
  213.         return 1;
  214.     }
  215.     return 0;
  216. }
  217. int read_sms(int type, int *x, int *y, int *z)
  218. {
  219.     int _x, _y, _z;
  220.     int xoff, yoff, zoff;
  221.     Boolean ok;
  222.     int ret;
  223.  
  224.     ret = read_sms_raw(type, &_x, &_y, &_z);
  225.     if ( !ret )
  226.         return 0;
  227.     static CFStringRef app = CFSTR("com.ramsayl.UniMotion");
  228.     static CFStringRef xoffstr = CFSTR("x_offset");
  229.     static CFStringRef yoffstr = CFSTR("y_offset");
  230.     static CFStringRef zoffstr = CFSTR("z_offset");
  231.     xoff = CFPreferencesGetAppIntegerValue(xoffstr, app, &ok);
  232.     if ( ok ) _x += xoff;
  233.     yoff = CFPreferencesGetAppIntegerValue(yoffstr, app, &ok);
  234.     if ( ok ) _y += yoff;
  235.     zoff = CFPreferencesGetAppIntegerValue(zoffstr, app, &ok);
  236.     if ( ok ) _z += zoff;
  237.     
  238.     *x = _x;
  239.     *y = _y;
  240.     *z = _z;
  241.     return ret;
  242. }
  243. int read_sms_real(int type, double *x, double *y, double *z)
  244. {
  245.     int _x, _y, _z;
  246.     int xscale, yscale, zscale;
  247.     int ret;
  248.     Boolean ok;
  249.  
  250.     ret = read_sms_raw(type, &_x, &_y, &_z);
  251.     if ( !ret )
  252.         return 0;
  253.     static CFStringRef app = CFSTR("com.ramsayl.UniMotion");
  254.     static CFStringRef xscalestr = CFSTR("x_scale");
  255.     static CFStringRef yscalestr = CFSTR("y_scale");
  256.     static CFStringRef zscalestr = CFSTR("z_scale");
  257.     xscale = CFPreferencesGetAppIntegerValue(xscalestr, app, &ok);
  258.     if ( !ok ) return 0;
  259.     yscale = CFPreferencesGetAppIntegerValue(yscalestr, app, &ok);
  260.     if ( !ok ) return 0;
  261.     zscale = CFPreferencesGetAppIntegerValue(zscalestr, app, &ok);
  262.     if ( !ok ) return 0;
  263.     
  264.     *x = _x / (double)xscale;
  265.     *y = _y / (double)yscale;
  266.     *z = _z / (double)zscale;
  267.     
  268.     return 1;
  269. }
  270. #endif