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 %s\n", entry->vendor, entry->product);
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 %s\n", entry->vendor, entry->product);
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("      <!-- %s %s -->\n", entry->vendor, entry->product);
00135           printf("      <match key=\"usb.vendor_id\" int=\"0x%04x\">\n", entry->vendor_id);
00136           printf("        <match key=\"usb.product_id\" int=\"0x%04x\">\n", entry->product_id);
00137           /* FIXME: If hal >=0.5.10 can be depended upon, the matches below with contains_not can instead use addset */
00138           printf("          <match key=\"info.capabilities\" contains_not=\"portable_audio_player\">\n");
00139           printf("            <append key=\"info.capabilities\" type=\"strlist\">portable_audio_player</append>\n");
00140           printf("          </match>\n");
00141           printf("          <merge key=\"info.vendor\" type=\"string\">%s</merge>\n", entry->vendor);
00142           printf("          <merge key=\"info.product\" type=\"string\">%s</merge>\n", entry->product);
00143           printf("          <merge key=\"info.category\" type=\"string\">portable_audio_player</merge>\n");
00144           printf("          <merge key=\"portable_audio_player.access_method\" type=\"string\">user</merge>\n");
00145           printf("          <match key=\"portable_audio_player.access_method.protocols\" contains_not=\"mtp\">\n");
00146           printf("            <append key=\"portable_audio_player.access_method.protocols\" type=\"strlist\">mtp</append>\n");
00147           printf("          </match>\n");
00148           printf("          <append key=\"portable_audio_player.access_method.drivers\" type=\"strlist\">libmtp</append>\n");
00149           /* FIXME: needs true list of formats ... But all of them can do MP3 and WMA */
00150           printf("          <match key=\"portable_audio_player.output_formats\" contains_not=\"audio/mpeg\">\n");
00151           printf("            <append key=\"portable_audio_player.output_formats\" type=\"strlist\">audio/mpeg</append>\n");
00152           printf("          </match>\n");
00153           printf("          <match key=\"portable_audio_player.output_formats\" contains_not=\"audio/x-ms-wma\">\n");
00154           printf("            <append key=\"portable_audio_player.output_formats\" type=\"strlist\">audio/x-ms-wma</append>\n");
00155           printf("          </match>\n");
00156           /* Special hack to support the OGG format - irivers, TrekStor and NormSoft (Palm) can always play these files! */
00157           if (entry->vendor_id == 0x4102 || // iriver
00158               entry->vendor_id == 0x066f || // TrekStor
00159               entry->vendor_id == 0x1703) { // NormSoft, Inc.
00160             printf("          <match key=\"portable_audio_player.output_formats\" contains_not=\"application/ogg\">\n");
00161             printf("            <append key=\"portable_audio_player.output_formats\" type=\"strlist\">application/ogg</append>\n");
00162             printf("          </match>\n");
00163           }
00164           printf("          <merge key=\"portable_audio_player.libmtp.protocol\" type=\"string\">mtp</merge>\n");
00165           printf("        </match>\n");
00166           printf("      </match>\n");
00167         break;
00168         case style_usbids:
00169           if (last_vendor != entry->vendor_id) {
00170             printf("%04x\n", entry->vendor_id);
00171           }
00172           printf("\t%04x  %s %s\n", entry->product_id, entry->vendor, entry->product);
00173         break;
00174       }
00175       last_vendor = entry->vendor_id;
00176     }
00177   } else {
00178     printf("Error.\n");
00179     exit(1);
00180   }
00181 
00182   // For backward comparibility with the #$!+@! ever changing
00183   // udev rule style...
00184   if (style == style_udev) {
00185     printf("GOTO=\"libmtp_rules_end\"\n\n");
00186     printf("LABEL=\"libmtp_usb_device_rules\"\n");
00187     for (i = 0; i < numentries; i++) {
00188       LIBMTP_device_entry_t * entry = &entries[i];
00189 
00190       printf("# %s %s\n", entry->vendor, entry->product);
00191       printf("ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action); 
00192     }
00193     printf("GOTO=\"libmtp_rules_end\"\n\n");
00194   }
00195 
00196   // Then the footer.
00197   switch (style) {
00198   case style_usbmap:
00199     break;
00200   case style_udev:
00201     printf("LABEL=\"libmtp_rules_end\"\n");
00202     break;
00203   case style_hal:
00204     printf("    </match>\n");
00205     printf("  </device>\n");
00206     printf("</deviceinfo>\n");
00207     break;
00208   case style_usbids:
00209     printf("\n");
00210   }
00211 
00212   exit (0);
00213 }

Generated on Sun Jan 27 12:08:40 2008 for libmtp by  doxygen 1.5.2