Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

mediactrl.c

Go to the documentation of this file.
00001 /*
00002 * mediactrl.c -- Jog Shuttle device support
00003 * Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
00004 *
00005 * This program is free software; you can redistribute it and/or modify
00006 * it under the terms of the GNU General Public License as published by
00007 * the Free Software Foundation; either version 2 of the License, or
00008 * (at your option) any later version.
00009 *
00010 * This program is distributed in the hope that it will be useful,
00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 * GNU General Public License for more details.
00014 *
00015 * You should have received a copy of the GNU General Public License
00016 * along with this program; if not, write to the Free Software Foundation,
00017 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 #include <stdlib.h>
00020 #include <stdio.h>
00021 #include <sys/ioctl.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 #include <sys/time.h>
00025 #include <asm/types.h>
00026 #include <fcntl.h>
00027 #include <unistd.h>
00028 #include <stdint.h>
00029 #include <string.h>
00030 #include <errno.h>
00031 
00032 #include <linux/input.h>
00033 #include "mediactrl.h"
00034 
00035 
00036 static char *_shuttle_name = "Shuttle";
00037 static char *_jog_name = "Jog";
00038 
00039 /*
00040     ShuttlePro keys
00041 */
00042 static struct  media_ctrl_key mc_shuttle_pro_keys[] = {
00043     { 0x100, "Button 1", MEDIA_CTRL_F1 },
00044     { 0x101, "Button 2", MEDIA_CTRL_F2 },
00045     { 0x102, "Button 3", MEDIA_CTRL_F3 },
00046     { 0x103, "Button 4", MEDIA_CTRL_F4 },
00047     { 0x104, "Button 5", MEDIA_CTRL_B4 },
00048     { 0x105, "Button 6", MEDIA_CTRL_B2 },
00049     { 0x106, "Button 7", MEDIA_CTRL_B1 },
00050     { 0x107, "Button 8", MEDIA_CTRL_B3 },
00051     { 0x108, "Button 9", MEDIA_CTRL_B5 },
00052     { 0x109, "Button 10", MEDIA_CTRL_B6 },
00053     { 0x10a, "Button 11", MEDIA_CTRL_B7 },
00054     { 0x10b, "Button 12", MEDIA_CTRL_B8 },
00055     { 0x10c, "Button 13", MEDIA_CTRL_B9 },
00056     { 0, NULL, 0 }
00057 };
00058 
00059 
00060 /*
00061     ShuttleXPress keys
00062 */
00063 static struct  media_ctrl_key mc_shuttle_xpress_keys[] = {
00064     { 0x104, "Button B4", MEDIA_CTRL_B4 },
00065     { 0x105, "Button B2", MEDIA_CTRL_B2 },
00066     { 0x106, "Button B1", MEDIA_CTRL_B1 },
00067     { 0x107, "Button B3", MEDIA_CTRL_B3 },
00068     { 0x108, "Button B5", MEDIA_CTRL_B5 },
00069     { 0, NULL, 0 }
00070 };
00071 
00072 
00073 /*
00074     JLCooper MCS3 Keys
00075 */
00076 static struct  media_ctrl_key mc_jlcooper_mcs3_keys[] = {
00077     { 0x107, "F1", MEDIA_CTRL_F1 },
00078     { 0x101, "F2", MEDIA_CTRL_F2 },
00079     { 0x105, "F3", MEDIA_CTRL_F3 },
00080     { 0x102, "F4", MEDIA_CTRL_F4 },
00081     { 0x103, "F5", MEDIA_CTRL_F5 },
00082     { 0x104, "F6", MEDIA_CTRL_F6 },
00083     { 0x10d, "W1", MEDIA_CTRL_B6 },
00084     { 0x10e, "W2", MEDIA_CTRL_B4 },
00085     { 0x100, "W3", MEDIA_CTRL_B2 },
00086     { 0x106, "W4", MEDIA_CTRL_B1 },
00087     { 0x110, "W5", MEDIA_CTRL_B3 },
00088     { 0x111, "W6", MEDIA_CTRL_B5 },
00089     { 0x115, "W7", MEDIA_CTRL_B7 },
00090     { 0x116, "STICK_LEFT", MEDIA_CTRL_STICK_LEFT },
00091     { 0x113, "STICK_RIGHT", MEDIA_CTRL_STICK_RIGHT },
00092     { 0x114, "STICK_UP", MEDIA_CTRL_STICK_UP },
00093     { 0x112, "STICK_DOWN", MEDIA_CTRL_STICK_DOWN },
00094     { 0x10f, "Rewind", MEDIA_CTRL_REWIND },
00095     { 0x108, "Fast Forward", MEDIA_CTRL_FAST_FORWARD },
00096     { 0x109, "Stop", MEDIA_CTRL_STOP },
00097     { 0x10a, "Play", MEDIA_CTRL_PLAY },
00098     { 0x10b, "Record", MEDIA_CTRL_RECORD },
00099     { 0, NULL, 0 }
00100 };
00101 
00102 
00103 /*
00104     Griffin PowerMate
00105 */
00106 static struct media_ctrl_key mc_powermate_keys[] = {
00107     { BTN_0, "Button", MEDIA_CTRL_B1 },
00108     { 0, NULL, 0 }
00109 };
00110 
00111 
00112 /*
00113     X-Keys Jog/Shuttle
00114 */
00115 static struct  media_ctrl_key mc_x_keys[] = {
00116     { 0x102, "Button L1", MEDIA_CTRL_F1 },
00117     { 0x103, "Button L2", MEDIA_CTRL_F9 },
00118     { 0x104, "Button L3", MEDIA_CTRL_B1 },
00119     { 0x105, "Button L4", MEDIA_CTRL_B3 },
00120     { 0x106, "Button L5", MEDIA_CTRL_B5 },
00121     { 0x10a, "Button L6", MEDIA_CTRL_F2 },
00122     { 0x10b, "Button L7", MEDIA_CTRL_F10 },
00123     { 0x10c, "Button L8", MEDIA_CTRL_B2 },
00124     { 0x10d, "Button L9", MEDIA_CTRL_B4 },
00125     { 0x10e, "Button L10", MEDIA_CTRL_B6 },
00126     { 0x112, "Button C1", MEDIA_CTRL_F3 },
00127     { 0x11a, "Button C2", MEDIA_CTRL_F4 },
00128     { 0x122, "Button C3", MEDIA_CTRL_F5 },
00129     { 0x12a, "Button C4", MEDIA_CTRL_F6 },
00130     { 0x113, "Button C5", MEDIA_CTRL_F11 },
00131     { 0x11b, "Button C6", MEDIA_CTRL_F12 },
00132     { 0x123, "Button C7", MEDIA_CTRL_F13 },
00133     { 0x12b, "Button C8", MEDIA_CTRL_F14 },
00134     { 0x132, "Button R1", MEDIA_CTRL_F7 },
00135     { 0x133, "Button R2", MEDIA_CTRL_F15 },
00136     { 0x134, "Button R3", MEDIA_CTRL_B7 },
00137     { 0x135, "Button R4", MEDIA_CTRL_B9 },
00138     { 0x136, "Button R5", MEDIA_CTRL_B11 },
00139     { 0x13a, "Button R6", MEDIA_CTRL_F8 },
00140     { 0x13b, "Button R7", MEDIA_CTRL_F16 },
00141     { 0x13c, "Button R8", MEDIA_CTRL_B8 },
00142     { 0x13d, "Button R9", MEDIA_CTRL_B10 },
00143     { 0x13e, "Button R10", MEDIA_CTRL_B12 },
00144     { 0, NULL, 0 }
00145 };
00146 
00147 struct  media_ctrl_key *media_ctrl_get_key(struct media_ctrl *ctrl, int code, int *index)
00148 {
00149     int i = 0;
00150     struct media_ctrl_key *keys = ctrl->device->keys;
00151     
00152     while ( keys[i].key != 0 ) {
00153         if (keys[i].key == code) {
00154             if (index != NULL)
00155                 *index = i;
00156             return &keys[i];
00157         }
00158         i++;
00159     }
00160     
00161     return NULL;
00162 }
00163 
00164 
00165 void translate_contour_hid_event(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me) 
00166 {
00167     
00168     int lv, cv;
00169     
00170     me->type = 0;
00171     
00172     if (ev->type == EV_REL) {
00173         /* First check the outer dial */
00174         if (ev->code == REL_WHEEL) {
00175             
00176             cv = (signed int)ev->value;
00177             if (cv == 1 || cv == -1 ) cv = 0;
00178             
00179                 
00180             if ( cv == ctrl->lastshu ) return;
00181             ctrl->lastshu = cv;
00182                 
00183             //printf("Shuttle: %d\n", cv);
00184             me->type  = MEDIA_CTRL_EVENT_SHUTTLE;
00185             me->value = cv*2;
00186             me->name = _shuttle_name;
00187             
00188         } else if  (ev->code == REL_DIAL) {
00189             
00190             if ( ctrl->lastval == -1 ) ctrl->lastval = ev->value;
00191             lv = ctrl->lastval;
00192             cv = ev->value;
00193 
00194             if ( lv == cv ) return;
00195                 
00196             ctrl->lastval = cv;
00197             
00198             if (cv < 10 && lv > 0xF0) cv +=0x100;
00199             if (lv < 10 && cv > 0xF0) lv +=0x100;
00200             
00201             me->type  = MEDIA_CTRL_EVENT_JOG;
00202             me->value = cv-lv;
00203             me->name = _jog_name;
00204             
00205             ctrl->jogpos += me->value;
00206             //printf("Jog: %06ld (%d)\n", ctrl->jogpos, me->value);
00207             }
00208         return;
00209     } else if (ev->type == EV_KEY) {
00210         int index;
00211         struct media_ctrl_key *key = media_ctrl_get_key(ctrl, ev->code, &index);
00212         if ( key == NULL ) return;
00213         
00214         me->type  = MEDIA_CTRL_EVENT_KEY;
00215         me->code = key->code;
00216         me->value = ev->value;
00217         me->name = ( char* )key->name;
00218         me->index = index;
00219          
00220         //printf("Key: %04x %02x: %s\n", ev->code, ev->value, key->name);
00221         
00222     }
00223     
00224 }
00225 
00226 void translate_compliant(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me) 
00227 {
00228     me->type = 0;
00229     
00230     // printf("Translate %02x %02x\n", ev->type, ev->code );
00231     
00232     if (ev->type == EV_REL) {
00233         if  (ev->code == REL_DIAL) {
00234             
00235             me->type  = MEDIA_CTRL_EVENT_JOG;
00236             me->value = (signed int)ev->value;
00237             me->name = _jog_name;
00238             
00239             ctrl->jogpos += me->value;
00240             //printf("Jog: %06ld (%d)\n", ctrl->jogpos, me->value);
00241         }
00242         return;
00243     } else if (ev->type == EV_ABS) {
00244         // printf("ABS\n" );
00245         if  ( ev->code == 0x1c || ev->code == ABS_THROTTLE ) {
00246             //printf("ABS_MISC\n" );
00247             me->type  = MEDIA_CTRL_EVENT_SHUTTLE;
00248             me->value = (signed int)ev->value;
00249             me->name = _shuttle_name;
00250             
00251             ctrl->shuttlepos = me->value;
00252             //printf("Shuttle: %06d (%d)\n", ctrl->shuttlepos, me->value);
00253         }
00254     } else if (ev->type == EV_KEY) {
00255         int index;
00256         struct media_ctrl_key *key = media_ctrl_get_key(ctrl, ev->code, &index);
00257         if ( key == NULL ) return;
00258         
00259         me->type  = MEDIA_CTRL_EVENT_KEY;
00260         me->code = key->code;
00261         me->value = ev->value;
00262         me->name = ( char* )key->name;
00263         me->index = index;
00264          
00265         //printf("Key: %04x %02x: %s\n", ev->code, ev->value, key->name);
00266         
00267     }
00268 }
00269 
00270 struct media_ctrl_device supported_devices[] = {
00271     { 0x0b33, 0x0030, "Contour ShuttlePRO v2", mc_shuttle_pro_keys, translate_contour_hid_event },
00272     { 0x0b33, 0x0020, "Contour ShuttleXPress", mc_shuttle_xpress_keys, translate_contour_hid_event },
00273     { 0x0b33, 0x0010, "Contour ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event },
00274     { 0x0b33, 0x0011, "Contour ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event }, /* Hercules OEM */
00275     { 0x05f3, 0x0240, "Contour ShuttlePro", mc_shuttle_pro_keys, translate_contour_hid_event },
00276     { 0x0760, 0x0001, "JLCooper MCS3", mc_jlcooper_mcs3_keys, translate_compliant },
00277     { 0x077d, 0x0410, "Griffin PowerMate", mc_powermate_keys, translate_compliant },
00278     { 0x05f3, 0x0241, "X-Keys Editor", mc_x_keys, translate_contour_hid_event },
00279     { 0, 0, 0 }
00280 };
00281 
00282 
00283 void media_ctrl_translate(struct media_ctrl *ctrl, struct input_event *ev, struct media_ctrl_event *me) 
00284 {
00285     if ( ctrl->device ) ctrl->device->translate(ctrl, ev, me);
00286 }
00287 
00288 
00289 void media_ctrl_read_event(struct media_ctrl *ctrl, struct media_ctrl_event *me) 
00290 {
00291     ssize_t n;
00292     struct input_event ev;
00293         
00294     // struct media_ctrl_event me;
00295     
00296     if ( ctrl->fd > 0 ) {
00297         n = read(ctrl->fd, &ev, sizeof(ev));
00298     } else {
00299         return;
00300     }
00301     
00302     if (n != sizeof(ev)) {
00303         //printf("JogShuttle::inputCallback: read: (%d) %s\n", errno, strerror(errno));
00304         close(ctrl->fd);
00305         ctrl->fd = 0;
00306         return;
00307     }
00308     
00309     if ( ctrl->device && ctrl->device->translate)
00310         ctrl->device->translate(ctrl, &ev, me);
00311     else
00312         me->type = 0;
00313     
00314     if ( me->type  == MEDIA_CTRL_EVENT_JOG ) {
00315         struct timeval timev;
00316         gettimeofday(&timev, NULL);
00317         unsigned long now = (unsigned long)timev.tv_usec + (1000000*(unsigned long)timev.tv_sec);
00318         if ( now < ctrl->last_jog_time + 40000 ) {
00319             //printf("*** Fast Jog %02d %05d ***\n", me->value, now - ctrl->last_jog_time);
00320             ctrl->jogrel = me->value;
00321             me->type = MEDIA_CTRL_EVENT_NONE;
00322         } else {
00323             me->value += ctrl->jogrel;
00324             ctrl->jogrel = 0;
00325             ctrl->last_jog_time = now;
00326             // printf("*** Jog %02d ***\n", me->value);
00327         }
00328     }
00329     
00330     return;
00331     
00332 }
00333 
00334 
00335 int probe_device(struct media_ctrl *mc)
00336 {
00337     short devinfo[4];
00338     int i = 0;
00339       
00340     if ( ioctl(mc->fd, EVIOCGID, &devinfo) ) {
00341         perror("evdev ioctl");
00342         return 0;
00343     }
00344     
00345     do {
00346         if ( supported_devices[i].vendor == devinfo[1] 
00347             && supported_devices[i].product == devinfo[2] ) {
00348                 
00349             mc->device = &supported_devices[i];
00350             //printf("Success on /dev/input/event%d: %s\n", mc->eventno, mc->device->name);
00351             // mc->fd = fd;
00352             // mc->translate = mc->device.translate_function;
00353             // mc = malloc(sizeof(struct media_ctrl));
00354             mc->jogpos  = 0;
00355             mc->lastval = -1;
00356             mc->last_jog_time = 0;
00357             return 1;
00358         } else {
00359             //mc->device = NULL;
00360         }
00361     
00362     } while ( supported_devices[++i].vendor != 0 );
00363             
00364     return 0;
00365 }
00366 
00367 
00368 void media_ctrl_get_device_list() 
00369 {
00370     // TBD
00371 }
00372 
00373 
00374 
00375 void find_first_device(struct media_ctrl *mc) 
00376 {
00377     char buf[256];
00378     int fd, i;
00379     
00380     for ( i = 0; i < 32; i++ ) {
00381         sprintf(buf, "/dev/input/event%d", i); 
00382         fd = open( buf, O_RDONLY );
00383         if ( fd < 0 ) {
00384             perror(buf);
00385         } else {
00386             mc->fd = fd;
00387             mc->eventno = i;
00388             if( probe_device(mc) ) {
00389                 return;
00390             } else {        
00391                 close(fd);
00392                 mc->fd = -1;
00393             }
00394         }
00395     }
00396     return;
00397 }
00398 
00399 
00400 void media_ctrl_close(struct media_ctrl *mc)
00401 {
00402     if (mc->fd > 0)
00403         close( mc->fd );
00404     memset( mc, 0, sizeof( struct media_ctrl ) );
00405 }
00406 
00407 
00408 void media_ctrl_open(struct media_ctrl *mc) 
00409 {
00410     find_first_device(mc);
00411 }

Generated on Sun Mar 11 22:11:46 2007 for Kino by  doxygen 1.4.2