| OLD | NEW |
| 1 /** | 1 /** |
| 2 * \file mtp-hotplug.c | 2 * \file mtp-hotplug.c |
| 3 * Program to create hotplug scripts. | 3 * Program to create hotplug scripts. |
| 4 * | 4 * |
| 5 * Copyright (C) 2005-2012 Linus Walleij <triad@df.lth.se> | 5 * Copyright (C) 2005-2012 Linus Walleij <triad@df.lth.se> |
| 6 * Copyright (C) 2006-2008 Marcus Meissner <marcus@jet.franken.de> | 6 * Copyright (C) 2006-2008 Marcus Meissner <marcus@jet.franken.de> |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Lesser General Public | 9 * modify it under the terms of the GNU Lesser General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 */ | 22 */ |
| 23 #include <libmtp.h> | 23 #include <libmtp.h> |
| 24 #include <unistd.h> | 24 #include <unistd.h> |
| 25 #include <stdlib.h> | 25 #include <stdlib.h> |
| 26 #include <stdio.h> | 26 #include <stdio.h> |
| 27 #include <string.h> | 27 #include <string.h> |
| 28 | 28 |
| 29 static void usage(void) | 29 static void usage(void) |
| 30 { | 30 { |
| 31 fprintf(stderr, "usage: hotplug [-u -H -i -a\"ACTION\"] -p\"DIR\" -g\"GROUP\"
-m\"MODE\"\n"); | 31 fprintf(stderr, "usage: hotplug [-u -H -i -a\"ACTION\"] -p\"DIR\" -g\"GROUP\"
-m\"MODE\"\n"); |
| 32 fprintf(stderr, " -w: use hwdb syntax\n"); | |
| 33 fprintf(stderr, " -u: use udev syntax\n"); | 32 fprintf(stderr, " -u: use udev syntax\n"); |
| 34 fprintf(stderr, " -o: use old udev syntax\n"); | 33 fprintf(stderr, " -o: use old udev syntax\n"); |
| 35 fprintf(stderr, " -H: use hal syntax\n"); | 34 fprintf(stderr, " -H: use hal syntax\n"); |
| 36 fprintf(stderr, " -i: use usb.ids simple list syntax\n"); | 35 fprintf(stderr, " -i: use usb.ids simple list syntax\n"); |
| 37 fprintf(stderr, " -a\"ACTION\": perform udev action ACTION on attachment
\n"); | 36 fprintf(stderr, " -a\"ACTION\": perform udev action ACTION on attachment
\n"); |
| 38 fprintf(stderr, " -p\"DIR\": directory where mtp-probe will be installed
\n"); | 37 fprintf(stderr, " -p\"DIR\": directory where mtp-probe will be installed
\n"); |
| 39 fprintf(stderr, " -g\"GROUP\": file group for device nodes\n"); | 38 fprintf(stderr, " -g\"GROUP\": file group for device nodes\n"); |
| 40 fprintf(stderr, " -m\"MODE\": file mode for device nodes\n"); | 39 fprintf(stderr, " -m\"MODE\": file mode for device nodes\n"); |
| 41 exit(1); | 40 exit(1); |
| 42 } | 41 } |
| 43 | 42 |
| 44 enum style { | 43 enum style { |
| 45 style_usbmap, | 44 style_usbmap, |
| 46 style_udev, | 45 style_udev, |
| 47 style_udev_old, | 46 style_udev_old, |
| 48 style_hal, | 47 style_hal, |
| 49 style_usbids, | 48 style_usbids |
| 50 style_hwdb | |
| 51 }; | 49 }; |
| 52 | 50 |
| 53 int main (int argc, char **argv) | 51 int main (int argc, char **argv) |
| 54 { | 52 { |
| 55 LIBMTP_device_entry_t *entries; | 53 LIBMTP_device_entry_t *entries; |
| 56 int numentries; | 54 int numentries; |
| 57 int i; | 55 int i; |
| 58 int ret; | 56 int ret; |
| 59 enum style style = style_usbmap; | 57 enum style style = style_usbmap; |
| 60 int opt; | 58 int opt; |
| 61 extern int optind; | 59 extern int optind; |
| 62 extern char *optarg; | 60 extern char *optarg; |
| 63 char *udev_action = NULL; | 61 char *udev_action = NULL; |
| 64 /* | 62 /* |
| 65 * You could tag on MODE="0666" here to enfore writeable | 63 * You could tag on MODE="0666" here to enfore writeable |
| 66 * device nodes, use the command line argument for that. | 64 * device nodes, use the command line argument for that. |
| 67 * Current udev default rules will make any device tagged | 65 * Current udev default rules will make any device tagged |
| 68 * with ENV{ID_MEDIA_PLAYER}=1 writable for the console | 66 * with ENV{ID_MEDIA_PLAYER}=1 writable for the console |
| 69 * user. | 67 * user. |
| 70 */ | 68 */ |
| 71 char default_udev_action[] = "SYMLINK+=\"libmtp-%k\", ENV{ID_MTP_DEVICE}=\"1\"
, ENV{ID_MEDIA_PLAYER}=\"1\""; | 69 char default_udev_action[] = "SYMLINK+=\"libmtp-%k\", ENV{ID_MTP_DEVICE}=\"1\"
, ENV{ID_MEDIA_PLAYER}=\"1\""; |
| 72 char *action; // To hold the action actually used. | 70 char *action; // To hold the action actually used. |
| 73 uint16_t last_vendor = 0x0000U; | 71 uint16_t last_vendor = 0x0000U; |
| 74 char mtp_probe_dir[256]; | 72 char mtp_probe_dir[256]; |
| 75 char *udev_group= NULL; | 73 char *udev_group= NULL; |
| 76 char *udev_mode = NULL; | 74 char *udev_mode = NULL; |
| 77 | 75 |
| 78 while ( (opt = getopt(argc, argv, "wuoiHa:p:g:m:")) != -1 ) { | 76 while ( (opt = getopt(argc, argv, "uoiHa:p:g:m:")) != -1 ) { |
| 79 switch (opt) { | 77 switch (opt) { |
| 80 case 'a': | 78 case 'a': |
| 81 udev_action = strdup(optarg); | 79 udev_action = strdup(optarg); |
| 82 break; | 80 break; |
| 83 case 'u': | 81 case 'u': |
| 84 style = style_udev; | 82 style = style_udev; |
| 85 break; | 83 break; |
| 86 case 'o': | 84 case 'o': |
| 87 style = style_udev_old; | 85 style = style_udev_old; |
| 88 break; | 86 break; |
| 89 case 'H': | 87 case 'H': |
| 90 style = style_hal; | 88 style = style_hal; |
| 91 break; | 89 break; |
| 92 case 'i': | 90 case 'i': |
| 93 style = style_usbids; | 91 style = style_usbids; |
| 94 break; | 92 break; |
| 95 case 'w': | |
| 96 style = style_hwdb; | |
| 97 break; | |
| 98 case 'p': | 93 case 'p': |
| 99 strncpy(mtp_probe_dir,optarg,sizeof(mtp_probe_dir)); | 94 strncpy(mtp_probe_dir,optarg,sizeof(mtp_probe_dir)); |
| 100 mtp_probe_dir[sizeof(mtp_probe_dir)-1] = '\0'; | 95 mtp_probe_dir[sizeof(mtp_probe_dir)-1] = '\0'; |
| 101 if (strlen(mtp_probe_dir) <= 1) { | 96 if (strlen(mtp_probe_dir) <= 1) { |
| 102 printf("Supply some sane mtp-probe dir\n"); | 97 printf("Supply some sane mtp-probe dir\n"); |
| 103 exit(1); | 98 exit(1); |
| 104 } | 99 } |
| 105 /* Make sure the dir ends with '/' */ | 100 /* Make sure the dir ends with '/' */ |
| 106 if (mtp_probe_dir[strlen(mtp_probe_dir)-1] != '/') { | 101 if (mtp_probe_dir[strlen(mtp_probe_dir)-1] != '/') { |
| 107 int index = strlen(mtp_probe_dir); | 102 int index = strlen(mtp_probe_dir); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 printf("ATTR{idVendor}==\"085c\", GOTO=\"libmtp_rules_end\"\n"); | 147 printf("ATTR{idVendor}==\"085c\", GOTO=\"libmtp_rules_end\"\n"); |
| 153 printf("ATTR{idVendor}==\"0971\", GOTO=\"libmtp_rules_end\"\n"); | 148 printf("ATTR{idVendor}==\"0971\", GOTO=\"libmtp_rules_end\"\n"); |
| 154 printf("# Canon scanners that look like MTP devices (PID 0x22nn)\n"); | 149 printf("# Canon scanners that look like MTP devices (PID 0x22nn)\n"); |
| 155 printf("ATTR{idVendor}==\"04a9\", ATTR{idProduct}==\"22*\", GOTO=\"libmtp_
rules_end\"\n"); | 150 printf("ATTR{idVendor}==\"04a9\", ATTR{idProduct}==\"22*\", GOTO=\"libmtp_
rules_end\"\n"); |
| 156 printf("# Canon digital camera (EOS 3D) that looks like MTP device (PID 0x
3113)\n"); | 151 printf("# Canon digital camera (EOS 3D) that looks like MTP device (PID 0x
3113)\n"); |
| 157 printf("ATTR{idVendor}==\"04a9\", ATTR{idProduct}==\"3113\", GOTO=\"libmtp
_rules_end\"\n"); | 152 printf("ATTR{idVendor}==\"04a9\", ATTR{idProduct}==\"3113\", GOTO=\"libmtp
_rules_end\"\n"); |
| 158 printf("# Sensitive Atheros devices that look like MTP devices\n"); | 153 printf("# Sensitive Atheros devices that look like MTP devices\n"); |
| 159 printf("ATTR{idVendor}==\"0cf3\", GOTO=\"libmtp_rules_end\"\n"); | 154 printf("ATTR{idVendor}==\"0cf3\", GOTO=\"libmtp_rules_end\"\n"); |
| 160 printf("# Sensitive Atmel JTAG programmers\n"); | 155 printf("# Sensitive Atmel JTAG programmers\n"); |
| 161 printf("ATTR{idVendor}==\"03eb\", GOTO=\"libmtp_rules_end\"\n"); | 156 printf("ATTR{idVendor}==\"03eb\", GOTO=\"libmtp_rules_end\"\n"); |
| 162 printf("# Sensitive Philips device\n"); | |
| 163 printf("ATTR{idVendor}==\"0471\", ATTR{idProduct}==\"083f\", GOTO=\"libmtp
_rules_end\"\n"); | |
| 164 break; | 157 break; |
| 165 case style_udev_old: | 158 case style_udev_old: |
| 166 printf("# UDEV-style hotplug map for libmtp\n"); | 159 printf("# UDEV-style hotplug map for libmtp\n"); |
| 167 printf("# Put this file in /etc/udev/rules.d\n\n"); | 160 printf("# Put this file in /etc/udev/rules.d\n\n"); |
| 168 printf("ACTION!=\"add\", GOTO=\"libmtp_rules_end\"\n"); | 161 printf("ACTION!=\"add\", GOTO=\"libmtp_rules_end\"\n"); |
| 169 printf("ENV{MAJOR}!=\"?*\", GOTO=\"libmtp_rules_end\"\n"); | 162 printf("ENV{MAJOR}!=\"?*\", GOTO=\"libmtp_rules_end\"\n"); |
| 170 printf("SUBSYSTEM==\"usb_device\", GOTO=\"libmtp_usb_device_rules\"\n" | 163 printf("SUBSYSTEM==\"usb_device\", GOTO=\"libmtp_usb_device_rules\"\n" |
| 171 "GOTO=\"libmtp_rules_end\"\n\n" | 164 "GOTO=\"libmtp_rules_end\"\n\n" |
| 172 "LABEL=\"libmtp_usb_device_rules\"\n\n"); | 165 "LABEL=\"libmtp_usb_device_rules\"\n\n"); |
| 173 break; | 166 break; |
| 174 case style_usbmap: | 167 case style_usbmap: |
| 175 printf("# This usermap will call the script \"libmtp.sh\" whenever a known
MTP device is attached.\n\n"); | 168 printf("# This usermap will call the script \"libmtp.sh\" whenever a known
MTP device is attached.\n\n"); |
| 176 break; | 169 break; |
| 177 case style_hal: | 170 case style_hal: |
| 178 printf("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!-- -*- SGML -*-
-->\n"); | 171 printf("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!-- -*- SGML -*-
-->\n"); |
| 179 printf("<!-- This file was generated by %s - - fdi -->\n", argv[0]); | 172 printf("<!-- This file was generated by %s - - fdi -->\n", argv[0]); |
| 180 printf("<deviceinfo version=\"0.2\">\n"); | 173 printf("<deviceinfo version=\"0.2\">\n"); |
| 181 printf(" <device>\n"); | 174 printf(" <device>\n"); |
| 182 printf(" <match key=\"info.subsystem\" string=\"usb\">\n"); | 175 printf(" <match key=\"info.subsystem\" string=\"usb\">\n"); |
| 183 break; | 176 break; |
| 184 case style_usbids: | 177 case style_usbids: |
| 185 printf("# usb.ids style device list from libmtp\n"); | 178 printf("# usb.ids style device list from libmtp\n"); |
| 186 printf("# Compare: http://www.linux-usb.org/usb.ids\n"); | 179 printf("# Compare: http://www.linux-usb.org/usb.ids\n"); |
| 187 break; | 180 break; |
| 188 case style_hwdb: | |
| 189 printf("# hardware database file for libmtp supported devices\n"); | |
| 190 break; | |
| 191 } | 181 } |
| 192 | 182 |
| 193 for (i = 0; i < numentries; i++) { | 183 for (i = 0; i < numentries; i++) { |
| 194 LIBMTP_device_entry_t * entry = &entries[i]; | 184 LIBMTP_device_entry_t * entry = &entries[i]; |
| 195 | 185 |
| 196 switch (style) { | 186 switch (style) { |
| 197 case style_udev: | 187 case style_udev: |
| 198 case style_udev_old: | 188 case style_udev_old: |
| 199 printf("# %s %s\n", entry->vendor, entry->product); | 189 printf("# %s %s\n", entry->vendor, entry->product); |
| 200 printf("ATTR{idVendor}==\"%04x\", ATTR{idProduct}==\"%04x\", %s", entry-
>vendor_id, entry->product_id, action); | 190 printf("ATTR{idVendor}==\"%04x\", ATTR{idProduct}==\"%04x\", %s", entry-
>vendor_id, entry->product_id, action); |
| 201 if (udev_group != NULL) printf(", GROUP=\"%s\"", udev_group); | 191 if (udev_group != NULL) printf(", GROUP=\"%s\"", udev_group); |
| 202 if (udev_mode != NULL) printf(", MODE=\"%s\"", udev_mode); | 192 if (udev_mode != NULL) printf(", MODE=\"%s\"", udev_mode); |
| 203 printf("\n"); | 193 printf("\n"); |
| 204 break; | 194 break; |
| 205 case style_usbmap: | 195 case style_usbmap: |
| 206 printf("# %s %s\n", entry->vendor, entry->product); | 196 printf("# %s %s\n", entry->vendor, entry->product); |
| 207 printf("libmtp.sh 0x0003 0x%04x 0x%04x 0x0000 0x0000 0x00 0
x00 0x00 0x00 0x00 0x00 0x00000000\n", entry->vendor_id, entry->p
roduct_id); | 197 printf("libmtp.sh 0x0003 0x%04x 0x%04x 0x0000 0x0000 0x00 0
x00 0x00 0x00 0x00 0x00 0x00000000\n", entry->vendor_id, entry->p
roduct_id); |
| 208 break; | 198 break; |
| 209 case style_hal: | 199 case style_hal: |
| 210 printf(" <!-- %s %s -->\n", entry->vendor, entry->product); | 200 printf(" <!-- %s %s -->\n", entry->vendor, entry->product); |
| 211 printf(" <match key=\"usb.vendor_id\" int=\"0x%04x\">\n", entry->
vendor_id); | 201 printf(" <match key=\"usb.vendor_id\" int=\"0x%04x\">\n", entry->
vendor_id); |
| 212 printf(" <match key=\"usb.product_id\" int=\"0x%04x\">\n", entr
y->product_id); | 202 printf(" <match key=\"usb.product_id\" int=\"0x%04x\">\n", entr
y->product_id); |
| 213 /* FIXME: If hal >=0.5.10 can be depended upon, the matches below with
contains_not can instead use addset */ | 203 /* FIXME: If hal >=0.5.10 can be depended upon, the matches below with
contains_not can instead use addset */ |
| 214 printf(" <match key=\"info.capabilities\" contains_not=\"port
able_audio_player\">\n"); | 204 printf(" <match key=\"info.capabilities\" contains_not=\"port
able_audio_player\">\n"); |
| 215 printf(" <append key=\"info.capabilities\" type=\"strlist\"
>portable_audio_player</append>\n"); | 205 printf(" <append key=\"info.capabilities\" type=\"strlist\"
>portable_audio_player</append>\n"); |
| 216 printf(" </match>\n"); | 206 printf(" </match>\n"); |
| 217 printf(" <merge key=\"info.vendor\" type=\"string\">%s</merge
>\n", entry->vendor); | 207 printf(" <merge key=\"info.vendor\" type=\"string\">%s</merge
>\n", entry->vendor); |
| 218 printf(" <merge key=\"info.product\" type=\"string\">%s</merg
e>\n", entry->product); | 208 printf(" <merge key=\"info.product\" type=\"string\">%s</merg
e>\n", entry->product); |
| 219 printf(" <merge key=\"info.category\" type=\"string\">portabl
e_audio_player</merge>\n"); | 209 printf(" <merge key=\"info.category\" type=\"string\">portabl
e_audio_player</merge>\n"); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 234 entry->vendor_id == 0x066f || // TrekStor | 224 entry->vendor_id == 0x066f || // TrekStor |
| 235 entry->vendor_id == 0x1703) { // NormSoft, Inc. | 225 entry->vendor_id == 0x1703) { // NormSoft, Inc. |
| 236 printf(" <match key=\"portable_audio_player.output_formats\
" contains_not=\"application/ogg\">\n"); | 226 printf(" <match key=\"portable_audio_player.output_formats\
" contains_not=\"application/ogg\">\n"); |
| 237 printf(" <append key=\"portable_audio_player.output_forma
ts\" type=\"strlist\">application/ogg</append>\n"); | 227 printf(" <append key=\"portable_audio_player.output_forma
ts\" type=\"strlist\">application/ogg</append>\n"); |
| 238 printf(" </match>\n"); | 228 printf(" </match>\n"); |
| 239 } | 229 } |
| 240 printf(" <merge key=\"portable_audio_player.libmtp.protocol\"
type=\"string\">mtp</merge>\n"); | 230 printf(" <merge key=\"portable_audio_player.libmtp.protocol\"
type=\"string\">mtp</merge>\n"); |
| 241 printf(" </match>\n"); | 231 printf(" </match>\n"); |
| 242 printf(" </match>\n"); | 232 printf(" </match>\n"); |
| 243 break; | 233 break; |
| 244 case style_usbids: | 234 case style_usbids: |
| 245 if (last_vendor != entry->vendor_id) { | 235 if (last_vendor != entry->vendor_id) { |
| 246 printf("%04x\n", entry->vendor_id); | 236 printf("%04x\n", entry->vendor_id); |
| 247 } | 237 } |
| 248 printf("\t%04x %s %s\n", entry->product_id, entry->vendor, entry->pro
duct); | 238 printf("\t%04x %s %s\n", entry->product_id, entry->vendor, entry->pro
duct); |
| 249 break; | 239 break; |
| 250 case style_hwdb: | |
| 251 printf("# %s %s\n", entry->vendor, entry->product); | |
| 252 printf("usb:v%04xp%04x*\n", entry->vendor_id, entry->product_id); | |
| 253 printf(" ID_MEDIA_PLAYER=1\n"); | |
| 254 printf(" ID_MTP_DEVICE=1\n"); | |
| 255 printf("\n"); | |
| 256 break; | |
| 257 } | 240 } |
| 258 last_vendor = entry->vendor_id; | 241 last_vendor = entry->vendor_id; |
| 259 } | 242 } |
| 260 } else { | 243 } else { |
| 261 printf("Error.\n"); | 244 printf("Error.\n"); |
| 262 exit(1); | 245 exit(1); |
| 263 } | 246 } |
| 264 | 247 |
| 265 // Then the footer. | 248 // Then the footer. |
| 266 switch (style) { | 249 switch (style) { |
| 267 case style_usbmap: | 250 case style_usbmap: |
| 268 case style_hwdb: | |
| 269 break; | 251 break; |
| 270 case style_udev: | 252 case style_udev: |
| 271 case style_udev_old: | 253 case style_udev_old: |
| 272 /* | 254 /* |
| 273 * This is code that invokes the mtp-probe program on | 255 * This is code that invokes the mtp-probe program on |
| 274 * every USB device that is either PTP or vendor specific | 256 * every USB device that is either PTP or vendor specific |
| 275 */ | 257 */ |
| 276 printf("\n# Autoprobe vendor-specific, communication and PTP devices\n"); | 258 printf("\n# Autoprobe vendor-specific, communication and PTP devices\n"); |
| 277 printf("ENV{ID_MTP_DEVICE}!=\"1\", ENV{MTP_NO_PROBE}!=\"1\", ENV{COLOR_MEASU
REMENT_DEVICE}!=\"1\", ENV{libsane_matched}!=\"yes\", ATTR{bDeviceClass}==\"00|0
2|06|ef|ff\", PROGRAM=\"%smtp-probe /sys$env{DEVPATH} $attr{busnum} $attr{devnum
}\", RESULT==\"1\", %s", mtp_probe_dir, action); | 259 printf("ENV{ID_MTP_DEVICE}!=\"1\", ENV{MTP_NO_PROBE}!=\"1\", ENV{COLOR_MEASU
REMENT_DEVICE}!=\"1\", ENV{libsane_matched}!=\"yes\", ATTR{bDeviceClass}==\"00|0
2|06|ef|ff\", PROGRAM=\"%smtp-probe /sys$env{DEVPATH} $attr{busnum} $attr{devnum
}\", RESULT==\"1\", %s", mtp_probe_dir, action); |
| 278 if (udev_group != NULL) printf(", GROUP=\"%s\"", udev_group); | 260 if (udev_group != NULL) printf(", GROUP=\"%s\"", udev_group); |
| 279 if (udev_mode != NULL) printf(", MODE=\"%s\"", udev_mode); | 261 if (udev_mode != NULL) printf(", MODE=\"%s\"", udev_mode); |
| 280 printf("\n"); | 262 printf("\n"); |
| 281 printf("\nLABEL=\"libmtp_rules_end\"\n"); | 263 printf("\nLABEL=\"libmtp_rules_end\"\n"); |
| 282 break; | 264 break; |
| 283 case style_hal: | 265 case style_hal: |
| 284 printf(" </match>\n"); | 266 printf(" </match>\n"); |
| 285 printf(" </device>\n"); | 267 printf(" </device>\n"); |
| 286 printf("</deviceinfo>\n"); | 268 printf("</deviceinfo>\n"); |
| 287 break; | 269 break; |
| 288 case style_usbids: | 270 case style_usbids: |
| 289 printf("\n"); | 271 printf("\n"); |
| 290 } | 272 } |
| 291 | 273 |
| 292 exit (0); | 274 exit (0); |
| 293 } | 275 } |
| OLD | NEW |