4 * Copyright (C) 2008 Dan Williams <dcbw@redhat.com>
5 * Copyright (C) 2008 Peter Henn <support@option.com>
7 * Heavily based on the 'ozerocdoff' tool by Peter Henn.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details:
32 #include "ma8280p_us.h"
35 struct usb_dev_handle *handle = NULL;
37 typedef struct usb_device * (*FindFunc) (int vid, int pid);
38 typedef int (*SwitchFunc) (struct usb_dev_handle *dh, struct usb_device *dev);
46 typedef struct SwitchEntry {
50 SwitchFunc switch_func;
53 static SwitchEntry switch_types[] = {
54 { ST_OPTION_ZEROCD, "option-zerocd", option_zerocd_find, option_zerocd_switch },
55 { ST_MA8280P, "mobile-action-8280p", NULL, ma8280p_switch },
56 { ST_UNKNOWN, NULL, NULL }
59 static struct usb_device *
60 generic_find (int vid, int pid)
63 struct usb_device *dev;
65 for (bus = usb_get_busses(); bus; bus = bus->next) {
66 for (dev = bus->devices; dev; dev = dev->next) {
67 if (dev->descriptor.idVendor == vid && dev->descriptor.idProduct == pid) {
68 debug ("Found device '%s'", dev->filename);
77 release_usb_device (int param)
79 usb_release_interface (handle, 0);
86 printf ("Usage: modem-modeswitch [-hdq] [-l <file>] -v <vendor-id> -p <product-id> -t <type>\n"
87 " -h, --help show this help message\n"
88 " -v, --vendor <n> target USB vendor ID\n"
89 " -p, --product <n> target USB product ID\n"
90 " -t, --type <type> type of switch to attempt, varies by device:\n"
91 " option-zerocd - For many newer Option N.V. devices\n"
92 " mobile-action-8280p - For Mobile Action 8xxxP USB cables\n"
93 " -l, --log <file> log output to a file\n"
94 " -q, --quiet don't print anything to stdout\n"
95 " -d, --debug display debugging messages\n\n"
97 " modem-modeswitch -v 0x0af0 -p 0xc031 -t option-zerocd\n");
101 parse_type (const char *s)
103 SwitchEntry *entry = &switch_types[0];
105 while (entry->clopt) {
106 if (!strcmp (entry->clopt, s))
121 int main(int argc, char **argv)
123 static struct option options[] = {
124 { "help", no_argument, NULL, 'h' },
125 { "vendor", required_argument, NULL, 'v' },
126 { "product", required_argument, NULL, 'p' },
127 { "type", required_argument, NULL, 't' },
128 { "log", required_argument, NULL, 'l' },
129 { "debug", no_argument, NULL, 'd' },
130 { "quiet", no_argument, NULL, 'q' },
134 struct usb_device *dev;
135 int vid = 0, pid = 0;
136 const char *logpath = NULL;
138 int ret, quiet = 0, debug = 0;
139 SwitchEntry *sentry = NULL;
144 option = getopt_long(argc, argv, "hv:p:l:t:dq", options, NULL);
150 vid = strtol (optarg, NULL, 0);
153 pid = strtol (optarg, NULL, 0);
156 sentry = parse_type (optarg);
158 error ("unknown switch type '%s'", optarg);
179 if (log_startup (logpath, debug, quiet)) {
180 fprintf (stderr, "Couldn't open/create logfile %s", logpath);
188 error ("missing device switch type.");
196 error ("missing vendor and device IDs.");
202 if (usb_find_busses() < 0) {
203 error ("no USB busses found.");
207 if (usb_find_devices() < 0) {
208 error ("no USB devices found.");
212 if (sentry->find_func)
213 dev = (*sentry->find_func) (vid, pid);
215 dev = generic_find (vid, pid);
217 error ("no device found.");
221 handle = usb_open (dev);
222 if (handle == NULL) {
223 error ("%s: could not access the device.",
228 /* detach running default driver */
229 signal (SIGTERM, release_usb_device);
230 ret = usb_get_driver_np (handle, 0, buffer, sizeof (buffer));
232 debug ("%s: found already attached driver '%s'", dev->filename, buffer);
234 ret = usb_detach_kernel_driver_np (handle, 0);
236 debug ("%s: error: unable to detach current driver.", dev->filename);
242 ret = usb_claim_interface (handle, 0);
244 debug ("%s: couldn't claim device's USB interface: %d.",
250 ret = (*sentry->switch_func) (handle, dev);
252 debug ("%s: failed to switch device to modem mode.", dev->filename);
253 usb_release_interface (handle, 0);
258 usb_release_interface (handle, 0);
260 ret = usb_close (handle);
262 debug ("%s: failed to close the device.", dev->filename);