Home | History | Annotate | Download | only in examples
      1 /**
      2  * \file hotplug.c
      3  * Example program to create hotplug scripts.
      4  *
      5  * Copyright (C) 2005-2007 Linus Walleij <triad (at) df.lth.se>
      6  * Copyright (C) 2006-2008 Marcus Meissner <marcus (at) jet.franken.de>
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Lesser General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Lesser General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Lesser General Public
     19  * License along with this library; if not, write to the
     20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     21  * Boston, MA 02111-1307, USA.
     22  */
     23 #include "common.h"
     24 #include <unistd.h>
     25 #include <stdlib.h>
     26 #include <stdio.h>
     27 #include <string.h>
     28 
     29 static void usage(void)
     30 {
     31   fprintf(stderr, "usage: hotplug [-u -H -i -a\"ACTION\"]\n");
     32   fprintf(stderr, "       -u:  use udev syntax\n");
     33   fprintf(stderr, "       -H:  use hal syntax\n");
     34   fprintf(stderr, "       -i:  use usb.ids simple list syntax\n");
     35   fprintf(stderr, "       -a\"ACTION\": perform udev action ACTION on attachment\n");
     36   exit(1);
     37 }
     38 
     39 enum style {
     40   style_usbmap,
     41   style_udev,
     42   style_hal,
     43   style_usbids
     44 };
     45 
     46 int main (int argc, char **argv)
     47 {
     48   LIBMTP_device_entry_t *entries;
     49   int numentries;
     50   int i;
     51   int ret;
     52   enum style style = style_usbmap;
     53   int opt;
     54   extern int optind;
     55   extern char *optarg;
     56   char *udev_action = NULL;
     57   char default_udev_action[] = "SYMLINK+=\"libmtp-%k\", MODE=\"666\"";
     58   char *action; // To hold the action actually used.
     59   uint16_t last_vendor = 0x0000U;
     60 
     61   while ( (opt = getopt(argc, argv, "uUiHa:")) != -1 ) {
     62     switch (opt) {
     63     case 'a':
     64       udev_action = strdup(optarg);
     65     case 'u':
     66       style = style_udev;
     67       break;
     68     case 'H':
     69       style = style_hal;
     70       break;
     71     case 'i':
     72       style = style_usbids;
     73       break;
     74     default:
     75       usage();
     76     }
     77   }
     78 
     79   if (udev_action != NULL) {
     80     action = udev_action;
     81   } else {
     82     action = default_udev_action;
     83   }
     84 
     85   LIBMTP_Init();
     86   ret = LIBMTP_Get_Supported_Devices_List(&entries, &numentries);
     87   if (ret == 0) {
     88     switch (style) {
     89     case style_udev:
     90       printf("# UDEV-style hotplug map for libmtp\n");
     91       printf("# Put this file in /etc/udev/rules.d\n\n");
     92       printf("ACTION!=\"add\", GOTO=\"libmtp_rules_end\"\n");
     93       printf("ENV{MAJOR}!=\"?*\", GOTO=\"libmtp_rules_end\"\n");
     94       printf("SUBSYSTEM==\"usb\", GOTO=\"libmtp_usb_rules\"\n"
     95 	     "# The following thing will be deprecated when older kernels are phased out.\n"
     96              "SUBSYSTEM==\"usb_device\", GOTO=\"libmtp_usb_device_rules\"\n"
     97 	     "GOTO=\"libmtp_rules_end\"\n\n"
     98 	     "LABEL=\"libmtp_usb_rules\"\n\n");
     99       break;
    100     case style_usbmap:
    101       printf("# This usermap will call the script \"libmtp.sh\" whenever a known MTP device is attached.\n\n");
    102       break;
    103     case style_hal:
    104       printf("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!-- -*- SGML -*- -->\n");
    105       printf("<!-- This file was generated by %s - - fdi -->\n", argv[0]);
    106       printf("<deviceinfo version=\"0.2\">\n");
    107       printf("  <device>\n");
    108       printf("    <match key=\"info.subsystem\" string=\"usb\">\n");
    109       break;
    110     case style_usbids:
    111       printf("# usb.ids style device list from libmtp\n");
    112       printf("# Compare: http://www.linux-usb.org/usb.ids\n");
    113       break;
    114     }
    115 
    116     for (i = 0; i < numentries; i++) {
    117       LIBMTP_device_entry_t * entry = &entries[i];
    118 
    119       switch (style) {
    120       case style_udev:
    121 	{
    122           printf("# %s %s\n", entry->vendor, entry->product);
    123 	  // Old style directly SYSFS named.
    124 	  // printf("SYSFS{idVendor}==\"%04x\", SYSFS{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action);
    125 	  // Newer style
    126 	  printf("ATTR{idVendor}==\"%04x\", ATTR{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action);
    127 	  break;
    128         }
    129       case style_usbmap:
    130           printf("# %s %s\n", entry->vendor, entry->product);
    131           printf("libmtp.sh    0x0003  0x%04x  0x%04x  0x0000  0x0000  0x00    0x00    0x00    0x00    0x00    0x00    0x00000000\n", entry->vendor_id, entry->product_id);
    132           break;
    133         case style_hal:
    134           printf("      <!-- %s %s -->\n", entry->vendor, entry->product);
    135           printf("      <match key=\"usb.vendor_id\" int=\"0x%04x\">\n", entry->vendor_id);
    136           printf("        <match key=\"usb.product_id\" int=\"0x%04x\">\n", entry->product_id);
    137           /* FIXME: If hal >=0.5.10 can be depended upon, the matches below with contains_not can instead use addset */
    138           printf("          <match key=\"info.capabilities\" contains_not=\"portable_audio_player\">\n");
    139           printf("            <append key=\"info.capabilities\" type=\"strlist\">portable_audio_player</append>\n");
    140           printf("          </match>\n");
    141           printf("          <merge key=\"info.vendor\" type=\"string\">%s</merge>\n", entry->vendor);
    142           printf("          <merge key=\"info.product\" type=\"string\">%s</merge>\n", entry->product);
    143           printf("          <merge key=\"info.category\" type=\"string\">portable_audio_player</merge>\n");
    144           printf("          <merge key=\"portable_audio_player.access_method\" type=\"string\">user</merge>\n");
    145           printf("          <match key=\"portable_audio_player.access_method.protocols\" contains_not=\"mtp\">\n");
    146           printf("            <append key=\"portable_audio_player.access_method.protocols\" type=\"strlist\">mtp</append>\n");
    147           printf("          </match>\n");
    148           printf("          <append key=\"portable_audio_player.access_method.drivers\" type=\"strlist\">libmtp</append>\n");
    149           /* FIXME: needs true list of formats ... But all of them can do MP3 and WMA */
    150           printf("          <match key=\"portable_audio_player.output_formats\" contains_not=\"audio/mpeg\">\n");
    151           printf("            <append key=\"portable_audio_player.output_formats\" type=\"strlist\">audio/mpeg</append>\n");
    152           printf("          </match>\n");
    153           printf("          <match key=\"portable_audio_player.output_formats\" contains_not=\"audio/x-ms-wma\">\n");
    154           printf("            <append key=\"portable_audio_player.output_formats\" type=\"strlist\">audio/x-ms-wma</append>\n");
    155           printf("          </match>\n");
    156 	  /* Special hack to support the OGG format - irivers, TrekStor and NormSoft (Palm) can always play these files! */
    157 	  if (entry->vendor_id == 0x4102 || // iriver
    158 	      entry->vendor_id == 0x066f || // TrekStor
    159 	      entry->vendor_id == 0x1703) { // NormSoft, Inc.
    160 	    printf("          <match key=\"portable_audio_player.output_formats\" contains_not=\"application/ogg\">\n");
    161 	    printf("            <append key=\"portable_audio_player.output_formats\" type=\"strlist\">application/ogg</append>\n");
    162 	    printf("          </match>\n");
    163 	  }
    164           printf("          <merge key=\"portable_audio_player.libmtp.protocol\" type=\"string\">mtp</merge>\n");
    165           printf("        </match>\n");
    166           printf("      </match>\n");
    167         break;
    168         case style_usbids:
    169           if (last_vendor != entry->vendor_id) {
    170             printf("%04x\n", entry->vendor_id);
    171           }
    172           printf("\t%04x  %s %s\n", entry->product_id, entry->vendor, entry->product);
    173         break;
    174       }
    175       last_vendor = entry->vendor_id;
    176     }
    177   } else {
    178     printf("Error.\n");
    179     exit(1);
    180   }
    181 
    182   // For backward comparibility with the #$!+@! ever changing
    183   // udev rule style...
    184   if (style == style_udev) {
    185     printf("GOTO=\"libmtp_rules_end\"\n\n");
    186     printf("LABEL=\"libmtp_usb_device_rules\"\n");
    187     for (i = 0; i < numentries; i++) {
    188       LIBMTP_device_entry_t * entry = &entries[i];
    189 
    190       printf("# %s %s\n", entry->vendor, entry->product);
    191       printf("ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action);
    192     }
    193     printf("GOTO=\"libmtp_rules_end\"\n\n");
    194   }
    195 
    196   // Then the footer.
    197   switch (style) {
    198   case style_usbmap:
    199     break;
    200   case style_udev:
    201     printf("LABEL=\"libmtp_rules_end\"\n");
    202     break;
    203   case style_hal:
    204     printf("    </match>\n");
    205     printf("  </device>\n");
    206     printf("</deviceinfo>\n");
    207     break;
    208   case style_usbids:
    209     printf("\n");
    210   }
    211 
    212   exit (0);
    213 }
    214