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;
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
00124
00125
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
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
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
00157 if (entry->vendor_id == 0x4102 ||
00158 entry->vendor_id == 0x066f ||
00159 entry->vendor_id == 0x1703) {
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
00183
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
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 }