/** * \file hotplug.c * Example program to create hotplug scripts. * * Copyright (C) 2005-2007 Linus Walleij * Copyright (C) 2006-2008 Marcus Meissner * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "common.h" #include #include #include #include static void usage(void) { fprintf(stderr, "usage: hotplug [-u -H -i -a\"ACTION\"]\n"); fprintf(stderr, " -u: use udev syntax\n"); fprintf(stderr, " -H: use hal syntax\n"); fprintf(stderr, " -i: use usb.ids simple list syntax\n"); fprintf(stderr, " -a\"ACTION\": perform udev action ACTION on attachment\n"); exit(1); } enum style { style_usbmap, style_udev, style_hal, style_usbids }; int main (int argc, char **argv) { LIBMTP_device_entry_t *entries; int numentries; int i; int ret; enum style style = style_usbmap; int opt; extern int optind; extern char *optarg; char *udev_action = NULL; char default_udev_action[] = "SYMLINK+=\"libmtp-%k\", MODE=\"666\""; char *action; // To hold the action actually used. uint16_t last_vendor = 0x0000U; while ( (opt = getopt(argc, argv, "uUiHa:")) != -1 ) { switch (opt) { case 'a': udev_action = strdup(optarg); case 'u': style = style_udev; break; case 'H': style = style_hal; break; case 'i': style = style_usbids; break; default: usage(); } } if (udev_action != NULL) { action = udev_action; } else { action = default_udev_action; } LIBMTP_Init(); ret = LIBMTP_Get_Supported_Devices_List(&entries, &numentries); if (ret == 0) { switch (style) { case style_udev: printf("# UDEV-style hotplug map for libmtp\n"); printf("# Put this file in /etc/udev/rules.d\n\n"); printf("ACTION!=\"add\", GOTO=\"libmtp_rules_end\"\n"); printf("ATTR{dev}!=\"?*\", GOTO=\"libmtp_rules_end\"\n"); printf("SUBSYSTEM==\"usb\", GOTO=\"libmtp_usb_rules\"\n" "# The following thing will be deprecated when older kernels are phased out.\n" "SUBSYSTEM==\"usb_device\", GOTO=\"libmtp_usb_device_rules\"\n" "GOTO=\"libmtp_rules_end\"\n\n" "LABEL=\"libmtp_usb_rules\"\n\n"); break; case style_usbmap: printf("# This usermap will call the script \"libmtp.sh\" whenever a known MTP device is attached.\n\n"); break; case style_hal: printf(" \n"); printf("\n", argv[0]); printf("\n"); printf(" \n"); printf(" \n"); break; case style_usbids: printf("# usb.ids style device list from libmtp\n"); printf("# Compare: http://www.linux-usb.org/usb.ids\n"); break; } for (i = 0; i < numentries; i++) { LIBMTP_device_entry_t * entry = &entries[i]; switch (style) { case style_udev: { printf("# %s %s\n", entry->vendor, entry->product); // Old style directly SYSFS named. // printf("SYSFS{idVendor}==\"%04x\", SYSFS{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action); // Newer style printf("ATTR{idVendor}==\"%04x\", ATTR{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action); break; } case style_usbmap: printf("# %s %s\n", entry->vendor, entry->product); printf("libmtp.sh 0x0003 0x%04x 0x%04x 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000\n", entry->vendor_id, entry->product_id); break; case style_hal: printf(" \n", entry->vendor, entry->product); printf(" \n", entry->vendor_id); printf(" \n", entry->product_id); /* FIXME: If hal >=0.5.10 can be depended upon, the matches below with contains_not can instead use addset */ printf(" \n"); printf(" portable_audio_player\n"); printf(" \n"); printf(" %s\n", entry->vendor); printf(" %s\n", entry->product); printf(" portable_audio_player\n"); printf(" user\n"); printf(" \n"); printf(" mtp\n"); printf(" \n"); printf(" libmtp\n"); /* FIXME: needs true list of formats ... But all of them can do MP3 and WMA */ printf(" \n"); printf(" audio/mpeg\n"); printf(" \n"); printf(" \n"); printf(" audio/x-ms-wma\n"); printf(" \n"); /* Special hack to support the OGG format - irivers, TrekStor and NormSoft (Palm) can always play these files! */ if (entry->vendor_id == 0x4102 || // iriver entry->vendor_id == 0x066f || // TrekStor entry->vendor_id == 0x1703) { // NormSoft, Inc. printf(" \n"); printf(" application/ogg\n"); printf(" \n"); } printf(" mtp\n"); printf(" \n"); printf(" \n"); break; case style_usbids: if (last_vendor != entry->vendor_id) { printf("%04x\n", entry->vendor_id); } printf("\t%04x %s %s\n", entry->product_id, entry->vendor, entry->product); break; } last_vendor = entry->vendor_id; } } else { printf("Error.\n"); exit(1); } // For backward comparibility with the #$!+@! ever changing // udev rule style... if (style == style_udev) { printf("GOTO=\"libmtp_rules_end\"\n\n"); printf("LABEL=\"libmtp_usb_device_rules\"\n"); for (i = 0; i < numentries; i++) { LIBMTP_device_entry_t * entry = &entries[i]; printf("# %s %s\n", entry->vendor, entry->product); printf("ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action); } printf("GOTO=\"libmtp_rules_end\"\n\n"); } // Then the footer. switch (style) { case style_usbmap: break; case style_udev: printf("LABEL=\"libmtp_rules_end\"\n"); break; case style_hal: printf(" \n"); printf(" \n"); printf("\n"); break; case style_usbids: printf("\n"); } exit (0); }