mirror of
https://github.com/systemd/systemd.git
synced 2024-11-05 15:21:37 +03:00
4dd9b29135
Remove option modeswitching code; use usb_modeswitch already, people.
263 lines
5.9 KiB
C
263 lines
5.9 KiB
C
/*
|
|
* Mobile action cable mode switcher
|
|
*
|
|
* Copyright (C) 2008 - 2010 Dan Williams <dcbw@redhat.com>
|
|
* Copyright (C) 2008 Peter Henn <support@option.com>
|
|
*
|
|
* Heavily based on the 'ozerocdoff' tool by Peter Henn.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details:
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <stdarg.h>
|
|
#include <getopt.h>
|
|
|
|
#include <usb.h>
|
|
|
|
#include "utils.h"
|
|
|
|
#include "ma8280p_us.h"
|
|
|
|
struct usb_dev_handle *handle = NULL;
|
|
|
|
typedef struct usb_device * (*FindFunc) (int vid, int pid);
|
|
typedef int (*SwitchFunc) (struct usb_dev_handle *dh, struct usb_device *dev);
|
|
|
|
typedef enum {
|
|
ST_UNKNOWN = 0,
|
|
ST_MA8280P
|
|
} SwitchType;
|
|
|
|
typedef struct SwitchEntry {
|
|
SwitchType st;
|
|
const char *clopt;
|
|
FindFunc find_func;
|
|
SwitchFunc switch_func;
|
|
} SwitchEntry;
|
|
|
|
static SwitchEntry switch_types[] = {
|
|
{ ST_MA8280P, "mobile-action-8280p", NULL, ma8280p_switch },
|
|
{ ST_UNKNOWN, NULL, NULL }
|
|
};
|
|
|
|
static struct usb_device *
|
|
generic_find (int vid, int pid)
|
|
{
|
|
struct usb_bus *bus;
|
|
struct usb_device *dev;
|
|
|
|
for (bus = usb_get_busses(); bus; bus = bus->next) {
|
|
for (dev = bus->devices; dev; dev = dev->next) {
|
|
if (dev->descriptor.idVendor == vid && dev->descriptor.idProduct == pid) {
|
|
debug ("Found device '%s'", dev->filename);
|
|
return dev;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
release_usb_device (int param)
|
|
{
|
|
usb_release_interface (handle, 0);
|
|
usb_close (handle);
|
|
}
|
|
|
|
static void
|
|
print_usage (void)
|
|
{
|
|
printf ("Usage: mobile-action-modeswitch [-hdq] [-l <file>] -v <vendor-id> -p <product-id> -t <type>\n"
|
|
" -h, --help show this help message\n"
|
|
" -v, --vendor <n> target USB vendor ID\n"
|
|
" -p, --product <n> target USB product ID\n"
|
|
" -t, --type <type> type of switch to attempt, varies by device:\n"
|
|
" mobile-action-8280p - For Mobile Action 8xxxP USB cables\n"
|
|
" -l, --log <file> log output to a file\n"
|
|
" -q, --quiet don't print anything to stdout\n"
|
|
" -d, --debug display debugging messages\n\n"
|
|
"Examples:\n"
|
|
" mobile-action-modeswitch -v 0x0df7 -p 0x8000 -t mobile-action-8280p\n");
|
|
}
|
|
|
|
static SwitchEntry *
|
|
parse_type (const char *s)
|
|
{
|
|
SwitchEntry *entry = &switch_types[0];
|
|
|
|
while (entry->clopt) {
|
|
if (!strcmp (entry->clopt, s))
|
|
return entry;
|
|
entry++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
do_exit (int val)
|
|
{
|
|
log_shutdown ();
|
|
exit (val);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
static struct option options[] = {
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ "vendor", required_argument, NULL, 'v' },
|
|
{ "product", required_argument, NULL, 'p' },
|
|
{ "type", required_argument, NULL, 't' },
|
|
{ "log", required_argument, NULL, 'l' },
|
|
{ "debug", no_argument, NULL, 'd' },
|
|
{ "quiet", no_argument, NULL, 'q' },
|
|
{ NULL, 0, NULL, 0}
|
|
};
|
|
|
|
struct usb_device *dev;
|
|
int vid = 0, pid = 0;
|
|
const char *logpath = NULL;
|
|
char buffer[256];
|
|
int ret, quiet = 0, debug = 0;
|
|
SwitchEntry *sentry = NULL;
|
|
|
|
while (1) {
|
|
int option;
|
|
|
|
option = getopt_long(argc, argv, "hv:p:l:t:dq", options, NULL);
|
|
if (option == -1)
|
|
break;
|
|
|
|
switch (option) {
|
|
case 'v':
|
|
vid = strtol (optarg, NULL, 0);
|
|
break;
|
|
case 'p':
|
|
pid = strtol (optarg, NULL, 0);
|
|
break;
|
|
case 't':
|
|
sentry = parse_type (optarg);
|
|
if (!sentry) {
|
|
error ("unknown switch type '%s'", optarg);
|
|
print_usage ();
|
|
exit (1);
|
|
}
|
|
break;
|
|
case 'l':
|
|
logpath = optarg;
|
|
break;
|
|
case 'q':
|
|
quiet = 1;
|
|
break;
|
|
case 'd':
|
|
debug = 1;
|
|
break;
|
|
case 'h':
|
|
default:
|
|
print_usage ();
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
if (log_startup (logpath, debug, quiet)) {
|
|
fprintf (stderr, "Couldn't open/create logfile %s", logpath);
|
|
exit (2);
|
|
}
|
|
|
|
if (!sentry) {
|
|
if (!quiet)
|
|
print_usage ();
|
|
else
|
|
error ("missing device switch type.");
|
|
do_exit (3);
|
|
}
|
|
|
|
if (!vid || !pid) {
|
|
if (!quiet)
|
|
print_usage ();
|
|
else
|
|
error ("missing vendor and device IDs.");
|
|
do_exit (3);
|
|
}
|
|
|
|
usb_init();
|
|
|
|
if (usb_find_busses() < 0) {
|
|
error ("no USB busses found.");
|
|
do_exit (4);
|
|
}
|
|
|
|
if (usb_find_devices() < 0) {
|
|
error ("no USB devices found.");
|
|
do_exit (4);
|
|
}
|
|
|
|
if (sentry->find_func)
|
|
dev = (*sentry->find_func) (vid, pid);
|
|
else
|
|
dev = generic_find (vid, pid);
|
|
if (dev == NULL) {
|
|
error ("no device found.");
|
|
do_exit (5);
|
|
}
|
|
|
|
handle = usb_open (dev);
|
|
if (handle == NULL) {
|
|
error ("%s: could not access the device.",
|
|
dev->filename);
|
|
do_exit (6);
|
|
}
|
|
|
|
/* detach running default driver */
|
|
signal (SIGTERM, release_usb_device);
|
|
ret = usb_get_driver_np (handle, 0, buffer, sizeof (buffer));
|
|
if (ret == 0) {
|
|
debug ("%s: found already attached driver '%s'", dev->filename, buffer);
|
|
|
|
ret = usb_detach_kernel_driver_np (handle, 0);
|
|
if (ret != 0) {
|
|
debug ("%s: error: unable to detach current driver.", dev->filename);
|
|
usb_close (handle);
|
|
do_exit (7);
|
|
}
|
|
}
|
|
|
|
ret = usb_claim_interface (handle, 0);
|
|
if (ret != 0) {
|
|
debug ("%s: couldn't claim device's USB interface: %d.",
|
|
dev->filename, ret);
|
|
usb_close (handle);
|
|
do_exit (8);
|
|
}
|
|
|
|
ret = (*sentry->switch_func) (handle, dev);
|
|
if (ret < 0) {
|
|
debug ("%s: failed to switch device to serial mode.", dev->filename);
|
|
usb_release_interface (handle, 0);
|
|
usb_close (handle);
|
|
do_exit(9);
|
|
}
|
|
|
|
usb_release_interface (handle, 0);
|
|
|
|
ret = usb_close (handle);
|
|
if (ret < 0)
|
|
debug ("%s: failed to close the device.", dev->filename);
|
|
|
|
do_exit (0);
|
|
return 0;
|
|
}
|