13aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev/** 23aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * \file hotplug.c 33aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Example program to create hotplug scripts. 43aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * 53aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Copyright (C) 2005-2007 Linus Walleij <triad@df.lth.se> 63aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Copyright (C) 2006-2008 Marcus Meissner <marcus@jet.franken.de> 73aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * 83aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This library is free software; you can redistribute it and/or 93aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * modify it under the terms of the GNU Lesser General Public 103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * License as published by the Free Software Foundation; either 113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * version 2 of the License, or (at your option) any later version. 123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * 133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * This library is distributed in the hope that it will be useful, 143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * but WITHOUT ANY WARRANTY; without even the implied warranty of 153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Lesser General Public License for more details. 173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * 183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * You should have received a copy of the GNU Lesser General Public 193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * License along with this library; if not, write to the 203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev * Boston, MA 02111-1307, USA. 223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev */ 233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include "common.h" 243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <unistd.h> 253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <stdlib.h> 263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <stdio.h> 273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev#include <string.h> 283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevstatic void usage(void) 303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{ 313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev fprintf(stderr, "usage: hotplug [-u -H -i -a\"ACTION\"]\n"); 323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev fprintf(stderr, " -u: use udev syntax\n"); 333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev fprintf(stderr, " -H: use hal syntax\n"); 343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev fprintf(stderr, " -i: use usb.ids simple list syntax\n"); 353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev fprintf(stderr, " -a\"ACTION\": perform udev action ACTION on attachment\n"); 363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev exit(1); 373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev} 383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevenum style { 403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev style_usbmap, 413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev style_udev, 423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev style_hal, 433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev style_usbids 443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev}; 453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishevint main (int argc, char **argv) 473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev{ 483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev LIBMTP_device_entry_t *entries; 493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev int numentries; 503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev int i; 513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev int ret; 523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev enum style style = style_usbmap; 533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev int opt; 543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev extern int optind; 553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev extern char *optarg; 563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev char *udev_action = NULL; 573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev char default_udev_action[] = "SYMLINK+=\"libmtp-%k\", MODE=\"666\""; 583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev char *action; // To hold the action actually used. 593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev uint16_t last_vendor = 0x0000U; 603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev while ( (opt = getopt(argc, argv, "uUiHa:")) != -1 ) { 623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev switch (opt) { 633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case 'a': 643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev udev_action = strdup(optarg); 653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case 'u': 663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev style = style_udev; 673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case 'H': 693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev style = style_hal; 703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case 'i': 723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev style = style_usbids; 733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev default: 753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev usage(); 763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev if (udev_action != NULL) { 803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev action = udev_action; 813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } else { 823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev action = default_udev_action; 833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev LIBMTP_Init(); 863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev ret = LIBMTP_Get_Supported_Devices_List(&entries, &numentries); 873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev if (ret == 0) { 883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev switch (style) { 893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_udev: 903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("# UDEV-style hotplug map for libmtp\n"); 913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("# Put this file in /etc/udev/rules.d\n\n"); 923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("ACTION!=\"add\", GOTO=\"libmtp_rules_end\"\n"); 933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("ENV{MAJOR}!=\"?*\", GOTO=\"libmtp_rules_end\"\n"); 943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("SUBSYSTEM==\"usb\", GOTO=\"libmtp_usb_rules\"\n" 953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev "# The following thing will be deprecated when older kernels are phased out.\n" 963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev "SUBSYSTEM==\"usb_device\", GOTO=\"libmtp_usb_device_rules\"\n" 973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev "GOTO=\"libmtp_rules_end\"\n\n" 983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev "LABEL=\"libmtp_usb_rules\"\n\n"); 993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 1003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_usbmap: 1013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("# This usermap will call the script \"libmtp.sh\" whenever a known MTP device is attached.\n\n"); 1023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 1033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_hal: 1043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!-- -*- SGML -*- -->\n"); 1053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("<!-- This file was generated by %s - - fdi -->\n", argv[0]); 1063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("<deviceinfo version=\"0.2\">\n"); 1073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <device>\n"); 1083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <match key=\"info.subsystem\" string=\"usb\">\n"); 1093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 1103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_usbids: 1113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("# usb.ids style device list from libmtp\n"); 1123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("# Compare: http://www.linux-usb.org/usb.ids\n"); 1133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 1143aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 1153aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 1163aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev for (i = 0; i < numentries; i++) { 1173aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev LIBMTP_device_entry_t * entry = &entries[i]; 1183aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 1193aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev switch (style) { 1203aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_udev: 1213aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev { 1223aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("# %s %s\n", entry->vendor, entry->product); 1233aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev // Old style directly SYSFS named. 1243aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev // printf("SYSFS{idVendor}==\"%04x\", SYSFS{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action); 1253aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev // Newer style 1263aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("ATTR{idVendor}==\"%04x\", ATTR{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action); 1273aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 1283aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 1293aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_usbmap: 1303aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("# %s %s\n", entry->vendor, entry->product); 1313aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("libmtp.sh 0x0003 0x%04x 0x%04x 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000\n", entry->vendor_id, entry->product_id); 1323aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 1333aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_hal: 1343aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <!-- %s %s -->\n", entry->vendor, entry->product); 1353aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <match key=\"usb.vendor_id\" int=\"0x%04x\">\n", entry->vendor_id); 1363aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <match key=\"usb.product_id\" int=\"0x%04x\">\n", entry->product_id); 1373aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev /* FIXME: If hal >=0.5.10 can be depended upon, the matches below with contains_not can instead use addset */ 1383aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <match key=\"info.capabilities\" contains_not=\"portable_audio_player\">\n"); 1393aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <append key=\"info.capabilities\" type=\"strlist\">portable_audio_player</append>\n"); 1403aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" </match>\n"); 1413aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <merge key=\"info.vendor\" type=\"string\">%s</merge>\n", entry->vendor); 1423aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <merge key=\"info.product\" type=\"string\">%s</merge>\n", entry->product); 1433aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <merge key=\"info.category\" type=\"string\">portable_audio_player</merge>\n"); 1443aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <merge key=\"portable_audio_player.access_method\" type=\"string\">user</merge>\n"); 1453aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <match key=\"portable_audio_player.access_method.protocols\" contains_not=\"mtp\">\n"); 1463aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <append key=\"portable_audio_player.access_method.protocols\" type=\"strlist\">mtp</append>\n"); 1473aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" </match>\n"); 1483aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <append key=\"portable_audio_player.access_method.drivers\" type=\"strlist\">libmtp</append>\n"); 1493aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev /* FIXME: needs true list of formats ... But all of them can do MP3 and WMA */ 1503aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <match key=\"portable_audio_player.output_formats\" contains_not=\"audio/mpeg\">\n"); 1513aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <append key=\"portable_audio_player.output_formats\" type=\"strlist\">audio/mpeg</append>\n"); 1523aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" </match>\n"); 1533aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <match key=\"portable_audio_player.output_formats\" contains_not=\"audio/x-ms-wma\">\n"); 1543aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <append key=\"portable_audio_player.output_formats\" type=\"strlist\">audio/x-ms-wma</append>\n"); 1553aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" </match>\n"); 1563aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev /* Special hack to support the OGG format - irivers, TrekStor and NormSoft (Palm) can always play these files! */ 1573aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev if (entry->vendor_id == 0x4102 || // iriver 1583aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev entry->vendor_id == 0x066f || // TrekStor 1593aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev entry->vendor_id == 0x1703) { // NormSoft, Inc. 1603aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <match key=\"portable_audio_player.output_formats\" contains_not=\"application/ogg\">\n"); 1613aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <append key=\"portable_audio_player.output_formats\" type=\"strlist\">application/ogg</append>\n"); 1623aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" </match>\n"); 1633aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 1643aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" <merge key=\"portable_audio_player.libmtp.protocol\" type=\"string\">mtp</merge>\n"); 1653aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" </match>\n"); 1663aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" </match>\n"); 1673aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 1683aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_usbids: 1693aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev if (last_vendor != entry->vendor_id) { 1703aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("%04x\n", entry->vendor_id); 1713aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 1723aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("\t%04x %s %s\n", entry->product_id, entry->vendor, entry->product); 1733aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 1743aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 1753aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev last_vendor = entry->vendor_id; 1763aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 1773aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } else { 1783aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("Error.\n"); 1793aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev exit(1); 1803aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 1813aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 1823aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev // For backward comparibility with the #$!+@! ever changing 1833aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev // udev rule style... 1843aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev if (style == style_udev) { 1853aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("GOTO=\"libmtp_rules_end\"\n\n"); 1863aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("LABEL=\"libmtp_usb_device_rules\"\n"); 1873aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev for (i = 0; i < numentries; i++) { 1883aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev LIBMTP_device_entry_t * entry = &entries[i]; 1893aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 1903aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("# %s %s\n", entry->vendor, entry->product); 1913aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", %s\n", entry->vendor_id, entry->product_id, action); 1923aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 1933aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("GOTO=\"libmtp_rules_end\"\n\n"); 1943aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 1953aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 1963aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev // Then the footer. 1973aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev switch (style) { 1983aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_usbmap: 1993aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 2003aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_udev: 2013aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("LABEL=\"libmtp_rules_end\"\n"); 2023aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 2033aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_hal: 2043aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" </match>\n"); 2053aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf(" </device>\n"); 2063aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("</deviceinfo>\n"); 2073aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev break; 2083aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev case style_usbids: 2093aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev printf("\n"); 2103aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev } 2113aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev 2123aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev exit (0); 2133aa430dc5437a98734b36f996f9b17081a589143Yavor Goulishev} 214