hotplug.c

00001 
00023 #include "common.h"
00024 #include <unistd.h>
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 
00029 static void usage(void)
00030 {
00031   fprintf(stderr, "usage: hotplug [-u -H -i -a\"ACTION\"]\n");
00032   fprintf(stderr, "       -u:  use udev syntax\n");
00033   fprintf(stderr, "       -H:  use hal syntax\n");
00034   fprintf(stderr, "       -i:  use usb.ids simple list syntax\n");
00035   fprintf(stderr, "       -a\"ACTION\": perform udev action ACTION on attachment\n");
00036   exit(1);
00037 }
00038 
00039 enum style {
00040   style_usbmap,
00041   style_udev,
00042   style_hal,
00043   style_usbids
00044 };
00045 
00046 int main (int argc, char **argv)
00047 {
00048   LIBMTP_device_entry_t *entries;
00049   int numentries;
00050   int i;
00051   int ret;
00052   enum style style = style_usbmap;
00053   int opt;
00054   extern int optind;
00055   extern char *optarg;
00056   char *udev_action = NULL;
00057   char default_udev_action[] = "SYMLINK+=\"libmtp-%k\", MODE=\"666\"";
00058   char *action; // To hold the action actually used.
00059   uint16_t last_vendor = 0x0000U;  
00060 
00061   while ( (opt = getopt(argc, argv, "uUiHa:")) != -1 ) {
00062     switch (opt) {
00063     case 'a':
00064       udev_action = strdup(optarg);
00065     case 'u':
00066       style = style_udev;
00067       break;
00068     case 'H':
00069       style = style_hal;
00070       break;
00071     case 'i':
00072       style = style_usbids;
00073       break;
00074     default:
00075       usage();
00076     }
00077   }
00078 
00079   if (udev_action != NULL) {
00080     action = udev_action;
00081   } else {
00082     action = default_udev_action;
00083   }
00084 
00085   LIBMTP_Init();
00086   ret = LIBMTP_Get_Supported_Devices_List(&entries, &numentries);
00087   if (ret == 0) {
00088     switch (style) {
00089     case style_udev:
00090       printf("# UDEV-style hotplug map for libmtp\n");
00091       printf("# Put this file in /etc/udev/rules.d\n\n");
00092       printf("ACTION!=\"add\", GOTO=\"libmtp_rules_end\"\n");
00093       printf("ATTR{dev}!=\"?*\", GOTO=\"libmtp_rules_end\"\n");
00094       printf("SUBSYSTEM==\"usb\", GOTO=\"libmtp_usb_rules\"\n"
00095              "# The following thing will be deprecated when older kernels are phased out.\n"
00096              "SUBSYSTEM==\"usb_device\", GOTO=\"libmtp_usb_device_rules\"\n"
00097              "GOTO=\"libmtp_rules_end\"\n\n"
00098              "LABEL=\"libmtp_usb_rules\"\n\n");
00099       break;
00100     case style_usbmap:
00101       printf("# This usermap will call the script \"libmtp.sh\" whenever a known MTP device is attached.\n\n");
00102       break;
00103     case style_hal:
00104       printf("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!-- -*- SGML -*- -->\n");
00105       printf("<!-- This file was generated by %s - - fdi -->\n", argv[0]);
00106       printf("<deviceinfo version=\"0.2\">\n");
00107       printf("  <device>\n");
00108       printf("    <match key=\"info.bus\" string=\"usb\">\n");
00109       break;
00110     case style_usbids:
00111       printf("# usb.ids style device list from libmtp\n");
00112       printf("# Compare: http://www.linux-usb.org/usb.ids\n");
00113       break;
00114     }
00115 
00116     for (i = 0; i < numentries; i++) {
00117       LIBMTP_device_entry_t * entry = &entries[i];
00118 
00119       switch (style) {
00120       case style_udev: 
00121         {
00122           printf("# %s\n", entry->name);
00123           // Old style directly SYSFS named.
00124           // printf("SYSFS{idVendor}==\"%04x\", SYSFS{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action);
00125           // Newer style
00126           printf("ATTR{idVendor}==\"%04x\", ATTR{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action);
00127           break;
00128         }
00129       case style_usbmap:
00130           printf("# %s\n", entry->name);
00131           printf("libmtp.sh    0x0003  0x%04x  0x%04x  0x0000  0x0000  0x00    0x00    0x00    0x00    0x00    0x00    0x00000000\n", entry->vendor_id, entry->product_id);
00132           break;
00133         case style_hal:
00134           printf("      <match key=\"usb.vendor_id\" int=\"0x%04x\">\n", entry->vendor_id);
00135           printf("        <match key=\"usb.product_id\" int=\"0x%04x\">\n", entry->product_id);
00136           /* FIXME: If hal >=0.5.10 can be depended upon, the matches below with contains_not can instead use addset */
00137           printf("          <match key=\"info.capabilities\" contains_not=\"portable_audio_player\">\n");
00138           printf("            <append key=\"info.capabilities\" type=\"strlist\">portable_audio_player</append>\n");
00139           printf("          </match>\n");
00140           printf("          <merge key=\"info.category\" type=\"string\">portable_audio_player</merge>\n");
00141           printf("          <merge key=\"portable_audio_player.access_method\" type=\"string\">user</merge>\n");
00142           printf("          <match key=\"portable_audio_player.access_method.protocols\" contains_not=\"mtp\">\n");
00143           printf("            <append key=\"portable_audio_player.access_method.protocols\" type=\"strlist\">mtp</append>\n");
00144           printf("          </match>\n");
00145           printf("          <append key=\"portable_audio_player.access_method.drivers\" type=\"strlist\">libmtp</append>\n");
00146           /* FIXME: needs true list of formats ... But all of them can do MP3 and WMA */
00147           printf("          <match key=\"portable_audio_player.output_formats\" contains_not=\"audio/mpeg\">\n");
00148           printf("            <append key=\"portable_audio_player.output_formats\" type=\"strlist\">audio/mpeg</append>\n");
00149           printf("          </match>\n");
00150           printf("          <match key=\"portable_audio_player.output_formats\" contains_not=\"audio/x-ms-wma\">\n");
00151           printf("            <append key=\"portable_audio_player.output_formats\" type=\"strlist\">audio/x-ms-wma</append>\n");
00152           printf("          </match>\n");
00153           /* Special hack to support the OGG format - irivers, TrekStor and NormSoft (Palm) can always play these files! */
00154           if (entry->vendor_id == 0x4102 || // iriver
00155               entry->vendor_id == 0x066f || // TrekStor
00156               entry->vendor_id == 0x1703) { // NormSoft, Inc.
00157             printf("          <match key=\"portable_audio_player.output_formats\" contains_not=\"application/ogg\">\n");
00158             printf("            <append key=\"portable_audio_player.output_formats\" type=\"strlist\">application/ogg</append>\n");
00159             printf("          </match>\n");
00160           }
00161           printf("          <merge key=\"portable_audio_player.libmtp.protocol\" type=\"string\">mtp</merge>\n");
00162           printf("          <merge key=\"portable_audio_player.libmtp.name\" type=\"string\">%s</merge>\n", entry->name);
00163           printf("        </match>\n");
00164           printf("      </match>\n");
00165         break;
00166         case style_usbids:
00167           if (last_vendor != entry->vendor_id) {
00168             printf("%04x\n", entry->vendor_id);
00169           }
00170           printf("\t%04x  %s\n", entry->product_id, entry->name);
00171         break;
00172       }
00173       last_vendor = entry->vendor_id;
00174     }
00175   } else {
00176     printf("Error.\n");
00177     exit(1);
00178   }
00179 
00180   // For backward comparibility with the #$!+@! ever changing
00181   // udev rule style...
00182   if (style == style_udev) {
00183     printf("GOTO=\"libmtp_rules_end\"\n\n");
00184     printf("LABEL=\"libmtp_usb_device_rules\"\n");
00185     for (i = 0; i < numentries; i++) {
00186       LIBMTP_device_entry_t * entry = &entries[i];
00187 
00188       printf("# %s\n", entry->name);
00189       printf("ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action); 
00190     }
00191     printf("GOTO=\"libmtp_rules_end\"\n\n");
00192   }
00193 
00194   // Then the footer.
00195   switch (style) {
00196   case style_usbmap:
00197     break;
00198   case style_udev:
00199     printf("LABEL=\"libmtp_rules_end\"\n");
00200     break;
00201   case style_hal:
00202     printf("    </match>\n");
00203     printf("  </device>\n");
00204     printf("</deviceinfo>\n");
00205     break;
00206   case style_usbids:
00207     printf("\n");
00208   }
00209 
00210   exit (0);
00211 }

Generated on Thu Oct 4 18:38:12 2007 for libmtp by  doxygen 1.5.2