diff options
author | Dan Williams <dcbw@redhat.com> | 2009-03-15 23:29:31 -0400 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2009-03-15 23:29:31 -0400 |
commit | 9de7ff0c237c0353be5b8a720ddd64564a6095d6 (patch) | |
tree | b05a3fadb215051e1ffba78846c81c10332e7670 /modem-modeswitch | |
parent | 284e9c1e1fe208f880d8f21946bc8f0c4c061221 (diff) |
modem-modeswitch: huge refactor for Mobile Action 8xxxP USB cable support
Diffstat (limited to 'modem-modeswitch')
-rw-r--r-- | modem-modeswitch/61-mobile-action.rules | 9 | ||||
-rw-r--r-- | modem-modeswitch/61-option-modem-modeswitch.rules | 2 | ||||
-rw-r--r-- | modem-modeswitch/Makefile.am | 14 | ||||
-rw-r--r-- | modem-modeswitch/ma8280p_us.c | 455 | ||||
-rw-r--r-- | modem-modeswitch/ma8280p_us.h | 24 | ||||
-rw-r--r-- | modem-modeswitch/modem-modeswitch.8 | 2 | ||||
-rw-r--r-- | modem-modeswitch/modem-modeswitch.c | 204 | ||||
-rw-r--r-- | modem-modeswitch/option.c | 131 | ||||
-rw-r--r-- | modem-modeswitch/option.h | 29 | ||||
-rw-r--r-- | modem-modeswitch/utils.c | 83 | ||||
-rw-r--r-- | modem-modeswitch/utils.h | 32 |
11 files changed, 815 insertions, 170 deletions
diff --git a/modem-modeswitch/61-mobile-action.rules b/modem-modeswitch/61-mobile-action.rules new file mode 100644 index 0000000..bb99b43 --- /dev/null +++ b/modem-modeswitch/61-mobile-action.rules @@ -0,0 +1,9 @@ +ACTION!="add", GOTO="mobile_action_end" + +SUBSYSTEM=="usb", ATTR{bDeviceClass}=="ff", ATTR{bDeviceSubClass}=="ff", ENV{DEVTYPE}=="usb_device", GOTO="mobile_action_switch" +GOTO="mobile_action_end" + +LABEL="mobile_action_switch" +ATTRS{idVendor}=="0df7", ATTRS{idProduct}=="0800", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t mobile-action-8280p" + +LABEL="mobile_action_end" diff --git a/modem-modeswitch/61-option-modem-modeswitch.rules b/modem-modeswitch/61-option-modem-modeswitch.rules index 7eb3fe5..f97617e 100644 --- a/modem-modeswitch/61-option-modem-modeswitch.rules +++ b/modem-modeswitch/61-option-modem-modeswitch.rules @@ -1,6 +1,6 @@ ACTION!="add", GOTO="option_zerocd_end" -SUBSYSTEM=="usb", ATTR{bDeviceClass}!="ff" ,ENV{DEVTYPE}=="usb_device", GOTO="option_zerocd_disable" +SUBSYSTEM=="usb", ATTR{bDeviceClass}!="ff", ENV{DEVTYPE}=="usb_device", GOTO="option_zerocd_disable" SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", GOTO="option_zerocd_disable" GOTO="option_zerocd_end" diff --git a/modem-modeswitch/Makefile.am b/modem-modeswitch/Makefile.am index 706fd5a..b4e6ab4 100644 --- a/modem-modeswitch/Makefile.am +++ b/modem-modeswitch/Makefile.am @@ -3,11 +3,21 @@ include $(top_srcdir)/Makefile.am.inc udevhomedir = $(udev_prefix)/lib/udev udevhome_PROGRAMS = modem-modeswitch -modem_modeswitch_SOURCES = modem-modeswitch.c +modem_modeswitch_SOURCES = \ + modem-modeswitch.c \ + utils.c \ + utils.h \ + ma8280p_us.c \ + ma8280p_us.h \ + option.c \ + option.h + modem_modeswitch_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB_CFLAGS) modem_modeswitch_LDADD = $(LIBUSB_LIBS) udevrulesdir = $(udev_prefix)/lib/udev/rules.d -dist_udevrules_DATA = 61-option-modem-modeswitch.rules +dist_udevrules_DATA = \ + 61-option-modem-modeswitch.rules \ + 61-mobile-action.rules dist_man_MANS = modem-modeswitch.8 diff --git a/modem-modeswitch/ma8280p_us.c b/modem-modeswitch/ma8280p_us.c new file mode 100644 index 0000000..181eb63 --- /dev/null +++ b/modem-modeswitch/ma8280p_us.c @@ -0,0 +1,455 @@ +/* http://www.natox.be/ma8280p/ + * http://www.leopold.dk/~martin/ma-8230p.html + * http://figvam.blogspot.com/2007/01/mobile-action-8730p-usb-cable-and-linux.html + */ + +/* + * + * Code by davy hollevoet. This is simply an adaptation of code + * generated by usbsnoop2libusb. (http://iki.fi/lindi/usb/usbsnoop2libusb.pl) + * + * This code is released under both the GPL version 2 and BSD licenses. + * Either license may be used. + * + * GPLv2 + * ******** + * 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. + * + * In addition: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * BSD + * ****** + * Copyright (c) 1998, Regents of the University of California + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* This file is (mostly) generated with usbsnoop2libusb.pl from a usbsnoop log file. */ +/* Latest version of the script should be in http://iki.fi/lindi/usb/usbsnoop2libusb.pl */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <signal.h> +#include <ctype.h> +#include <usb.h> + +#include "utils.h" +#include "ma8280p_us.h" + +int ma8280p_switch (struct usb_dev_handle *devh, struct usb_device *dev) +{ + int ret = 1; + char *buf = NULL; + + buf = malloc (65535); + if (!buf) { + error ("%s: not enough memory", dev->filename, ret); + goto out; + } + + ret = usb_get_descriptor(devh, 0x0000001, 0x0000000, buf, 0x0000012); + usleep(6*1000); + ret = usb_get_descriptor(devh, 0x0000001, 0x0000000, buf, 0x0000012); + usleep(6*1000); + ret = usb_get_descriptor(devh, 0x0000002, 0x0000000, buf, 0x0000400); + usleep(10*1000); + ret = usb_release_interface(devh, 0); + if (ret != 0) + debug ("%s: failed to release interface before set_configuration: %d", dev->filename, ret); + ret = usb_set_configuration(devh, 0x0000001); + ret = usb_claim_interface(devh, 0); + if (ret != 0) + debug ("%s: claim after set_configuration failed with error %d", dev->filename, ret); + //ret = usb_set_altinterface(devh, 0); + //usleep(33*1000); + ret = usb_control_msg(devh, USB_TYPE_CLASS + USB_RECIP_INTERFACE + USB_ENDPOINT_IN, 0x0000001, 0x0000300, 0x0000000, buf, 0x0000008, 1000); + usleep(5*1000); + memcpy(buf, "\xb0\x04\x00\x00\x02\x90\x26\x86", 0x0000008); + ret = usb_control_msg(devh, USB_TYPE_CLASS + USB_RECIP_INTERFACE, 0x0000009, 0x0000300, 0x0000000, buf, 0x0000008, 1000); + usleep(4*1000); + memcpy(buf, "\xb0\x04\x00\x00\x02\x90\x26\x86", 0x0000008); + ret = usb_control_msg(devh, USB_TYPE_CLASS + USB_RECIP_INTERFACE, 0x0000009, 0x0000300, 0x0000000, buf, 0x0000008, 1000); + usleep(4*1000); + + usleep(4*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(6*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(1*1000); + //URB_FUNCTION_GET_STATUS_FROM_ENDPOINT skipped + usleep(4*1000); + memcpy(buf, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", 0x0000008); + ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000008, 1000); + usleep(3*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(1*1000); + memcpy(buf, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", 0x0000008); + ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000008, 1000); + usleep(7*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(1*1000); + memcpy(buf, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", 0x0000008); + ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000008, 1000); + usleep(7*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(2*1000); + //URB_FUNCTION_GET_STATUS_FROM_ENDPOINT skipped + usleep(4*1000); + memcpy(buf, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", 0x0000008); + ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000008, 1000); + usleep(2*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(1*1000); + memcpy(buf, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", 0x0000008); + ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000008, 1000); + usleep(7*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(1*1000); + memcpy(buf, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", 0x0000008); + ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000008, 1000); + usleep(7*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(8*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(1*1000); + //URB_FUNCTION_GET_STATUS_FROM_ENDPOINT skipped + usleep(4*1000); + memcpy(buf, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", 0x0000008); + ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000008, 1000); + usleep(3*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + usleep(1*1000); + //URB_FUNCTION_GET_STATUS_FROM_ENDPOINT skipped + usleep(4*1000); + memcpy(buf, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", 0x0000008); + ret = usb_interrupt_write(devh, 0x00000002, buf, 0x0000008, 1000); + usleep(3*1000); + ret = usb_interrupt_read(devh, 0x00000081, buf, 0x0000008, 1000); + +out: + if (buf) + free (buf); + return 0; +} diff --git a/modem-modeswitch/ma8280p_us.h b/modem-modeswitch/ma8280p_us.h new file mode 100644 index 0000000..bf0e304 --- /dev/null +++ b/modem-modeswitch/ma8280p_us.h @@ -0,0 +1,24 @@ +/* + * Modem mode switcher + * + * Copyright (C) 2009 Dan Williams <dcbw@redhat.com> + * + * 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: + */ + +#ifndef __MA8280P_H__ +#define __MA8280P_H__ + +#include <usb.h> + +int ma8280p_switch (struct usb_dev_handle *devh, struct usb_device *dev); + +#endif /* __MA8280P_H__ */ diff --git a/modem-modeswitch/modem-modeswitch.8 b/modem-modeswitch/modem-modeswitch.8 index 2c01202..80fab0d 100644 --- a/modem-modeswitch/modem-modeswitch.8 +++ b/modem-modeswitch/modem-modeswitch.8 @@ -23,7 +23,7 @@ the USB vendor ID of the mobile broadband device to switch the USB product ID of the mobile broadband device to switch .TP .BI \-\-type\ <type> -the type of switch to perform (one of: option-zerocd) +the type of switch to perform (one of: option-zerocd, mobile-action-8280p) .TP .BI \-\-log\ <file> log verbose debugging information about the switching process diff --git a/modem-modeswitch/modem-modeswitch.c b/modem-modeswitch/modem-modeswitch.c index 72e1966..a60ce7a 100644 --- a/modem-modeswitch/modem-modeswitch.c +++ b/modem-modeswitch/modem-modeswitch.c @@ -23,112 +23,41 @@ #include <unistd.h> #include <signal.h> #include <stdarg.h> -#include <time.h> #include <getopt.h> #include <usb.h> -/* Borrowed from /usr/include/linux/usb/ch9.h */ -#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_DIR_MASK 0x80 -#define USB_DIR_OUT 0 /* to device */ -#define USB_DIR_IN 0x80 /* to host */ +#include "utils.h" + +#include "ma8280p_us.h" +#include "option.h" -static int debug = 0; -static int quiet = 0; -static FILE *logfile = NULL; struct usb_dev_handle *handle = NULL; -typedef int (*SwitchFunc) (struct usb_dev_handle *dh, - int ep_in, - int ep_out, - const char *devname); +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_OPTION_ZEROCD + ST_OPTION_ZEROCD, + ST_MA8280P } SwitchType; typedef struct SwitchEntry { SwitchType st; const char *clopt; - SwitchFunc func; + FindFunc find_func; + SwitchFunc switch_func; } SwitchEntry; -/* Device-specific switcher functions */ -static int switch_option_zerocd (struct usb_dev_handle *dh, - int ep_in, - int ep_out, - const char *devname); - static SwitchEntry switch_types[] = { - { ST_OPTION_ZEROCD, "option-zerocd", switch_option_zerocd }, + { ST_OPTION_ZEROCD, "option-zerocd", option_zerocd_find, option_zerocd_switch }, + { ST_MA8280P, "mobile-action-8280p", NULL, ma8280p_switch }, { ST_UNKNOWN, NULL, NULL } }; - -static void -do_log (int err, const char *fmt, ...) -{ - va_list args; - char buffer[1024]; - - va_start (args, fmt); - vsnprintf (buffer, sizeof (buffer), fmt, args); - va_end (args); - - if (logfile) - fprintf (logfile, "%c: %s\n", err ? 'E' : 'L', buffer); - if (!quiet) - fprintf (err ? stderr : stdout, "%c: %s\n", err ? 'E' : 'L', buffer); -} - -#define logmsg(fmt, args...) do_log (0, fmt, ##args); -#define logerr(fmt, args...) do_log (1, fmt, ##args); - -#define debug(fmt, args...) \ -if (debug) { \ - logmsg ("%s(): " fmt, __func__, ##args); \ -} - -static int -switch_option_zerocd (struct usb_dev_handle *dh, - int ep_in, - int ep_out, - const char *devname) -{ - const char const rezero_cbw[] = { - 0x55, 0x53, 0x42, 0x43, /* bulk command signature (LE) */ - 0x78, 0x56, 0x34, 0x12, /* bulk command host tag */ - 0x01, 0x00, 0x00, 0x00, /* bulk command data transfer length (LE) */ - 0x80, /* flags: direction data-in */ - 0x00, /* LUN */ - 0x06, /* SCSI command length */ - 0x01, /* SCSI command: REZERO */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* filler */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - int ret; - char buffer[256]; - - /* Send the modeswitch command */ - ret = usb_bulk_write (dh, ep_out, (char *) rezero_cbw, sizeof (rezero_cbw), 1000); - if (ret < 0) - return ret; - - debug ("%s: REZERO command sent.", devname); - - /* Some devices need to be read from */ - ret = usb_bulk_read (dh, ep_in, buffer, sizeof (buffer), 1000); - - return ret; -} - - static struct usb_device * -find_device (int vid, int pid) +generic_find (int vid, int pid) { struct usb_bus *bus; struct usb_device *dev; @@ -136,49 +65,14 @@ find_device (int vid, int pid) 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 mass storage device:"); - debug (" Endpoints: %d", dev->config[0].interface[0].altsetting[0].bNumEndpoints); - debug (" Class: 0x%X", dev->config[0].interface[0].altsetting[0].bInterfaceClass); - debug (" SubClass: 0x%X", dev->config[0].interface[0].altsetting[0].bInterfaceSubClass); - debug (" Protocol: 0x%X", dev->config[0].interface[0].altsetting[0].bInterfaceProtocol); - - if ( (dev->config[0].interface[0].altsetting[0].bNumEndpoints == 2) - && (dev->config[0].interface[0].altsetting[0].bInterfaceClass == 0x08) - && (dev->config[0].interface[0].altsetting[0].bInterfaceSubClass == 0x06) - && (dev->config[0].interface[0].altsetting[0].bInterfaceProtocol == 0x50) ) { - debug ("Found modem mass storage device '%s'", dev->filename); - return dev; - } + debug ("Found device '%s'", dev->filename); + return dev; } } } return NULL; } -static int -find_endpoints (struct usb_device *dev, int *in_ep, int *out_ep) -{ - int i; - - for (i = 0; i < dev->config[0].interface[0].altsetting[0].bNumEndpoints; i++) { - struct usb_endpoint_descriptor *ep = &(dev->config[0].interface[0].altsetting[0].endpoint[i]); - - if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { - unsigned int direction = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; - - if (!*out_ep && (direction == USB_DIR_OUT)) - *out_ep = ep->bEndpointAddress; - else if (!*in_ep && (direction == USB_DIR_IN)) - *in_ep = ep->bEndpointAddress; - } - - if (*in_ep && *out_ep) - return 0; - } - - return -1; -} - static void release_usb_device (int param) { @@ -194,7 +88,8 @@ print_usage (void) " -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" - " option-zerocd - For many Option N.V. devices\n" + " option-zerocd - For many newer Option N.V. devices\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" @@ -208,8 +103,9 @@ parse_type (const char *s) SwitchEntry *entry = &switch_types[0]; while (entry->clopt) { - if (!strcmp (entry->clopt, "option-zerocd")) + if (!strcmp (entry->clopt, s)) return entry; + entry++; } return NULL; @@ -218,7 +114,7 @@ parse_type (const char *s) static void do_exit (int val) { - if (logfile) fclose (logfile); + log_shutdown (); exit (val); } @@ -236,10 +132,10 @@ int main(int argc, char **argv) }; struct usb_device *dev; - int vid = 0, pid = 0, bulk_in_ep = 0, bulk_out_ep = 0; + int vid = 0, pid = 0; const char *logpath = NULL; char buffer[256]; - int ret; + int ret, quiet = 0, debug = 0; SwitchEntry *sentry = NULL; while (1) { @@ -259,7 +155,7 @@ int main(int argc, char **argv) case 't': sentry = parse_type (optarg); if (!sentry) { - logerr ("unknown switch type '%s'", optarg); + error ("unknown switch type '%s'", optarg); print_usage (); exit (1); } @@ -280,23 +176,16 @@ int main(int argc, char **argv) } } - if (logpath) { - time_t t = time (NULL); - - logfile = fopen (logpath, "a+"); - if (!logfile) { - fprintf (stderr, "Couldn't open/create logfile %s", logpath); - exit (2); - } - - logmsg ("\n**** Started: %s\n", ctime (&t)); + if (log_startup (logpath, debug, quiet)) { + fprintf (stderr, "Couldn't open/create logfile %s", logpath); + exit (2); } if (!sentry) { if (!quiet) print_usage (); else - logerr ("missing device switch type."); + error ("missing device switch type."); do_exit (3); } @@ -304,31 +193,34 @@ int main(int argc, char **argv) if (!quiet) print_usage (); else - logerr ("missing vendor and device IDs."); + error ("missing vendor and device IDs."); do_exit (3); } usb_init(); if (usb_find_busses() < 0) { - logerr ("no USB busses found."); + error ("no USB busses found."); do_exit (4); } if (usb_find_devices() < 0) { - logerr ("no USB devices found."); + error ("no USB devices found."); do_exit (4); } - dev = find_device (vid, pid); + if (sentry->find_func) + dev = (*sentry->find_func) (vid, pid); + else + dev = generic_find (vid, pid); if (dev == NULL) { - logerr ("no mass storage device found."); + error ("no device found."); do_exit (5); } handle = usb_open (dev); if (handle == NULL) { - logerr ("%s: could not access the device.", + error ("%s: could not access the device.", dev->filename); do_exit (6); } @@ -355,32 +247,12 @@ int main(int argc, char **argv) do_exit (8); } - /* Find the device's bulk in and out endpoints */ - if (find_endpoints (dev, &bulk_in_ep, &bulk_out_ep) < 0) { - debug ("%s: couldn't find correct USB endpoints.", dev->filename); - usb_release_interface (handle, 0); - usb_close (handle); - do_exit (9); - } - - usb_clear_halt (handle, bulk_out_ep); - ret = usb_set_altinterface (handle, 0); - if (ret != 0) { - debug ("%s: couldn't set device alternate interface.", dev->filename); - usb_release_interface (handle, 0); - usb_close (handle); - do_exit (10); - } - - /* Let the mass storage device settle */ - sleep (1); - - ret = (*sentry->func) (handle, bulk_in_ep, bulk_out_ep, dev->filename); + ret = (*sentry->switch_func) (handle, dev); if (ret < 0) { debug ("%s: failed to switch device to modem mode.", dev->filename); usb_release_interface (handle, 0); usb_close (handle); - do_exit(11); + do_exit(9); } usb_release_interface (handle, 0); diff --git a/modem-modeswitch/option.c b/modem-modeswitch/option.c new file mode 100644 index 0000000..5b299fd --- /dev/null +++ b/modem-modeswitch/option.c @@ -0,0 +1,131 @@ +/* + * Modem mode switcher + * + * Copyright (C) 2008 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 <usb.h> + +#include "utils.h" +#include "option.h" + +/* Borrowed from /usr/include/linux/usb/ch9.h */ +#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_DIR_MASK 0x80 +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ + +struct usb_device * +option_zerocd_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 mass storage device:"); + debug (" Endpoints: %d", dev->config[0].interface[0].altsetting[0].bNumEndpoints); + debug (" Class: 0x%X", dev->config[0].interface[0].altsetting[0].bInterfaceClass); + debug (" SubClass: 0x%X", dev->config[0].interface[0].altsetting[0].bInterfaceSubClass); + debug (" Protocol: 0x%X", dev->config[0].interface[0].altsetting[0].bInterfaceProtocol); + + if ( (dev->config[0].interface[0].altsetting[0].bNumEndpoints == 2) + && (dev->config[0].interface[0].altsetting[0].bInterfaceClass == 0x08) + && (dev->config[0].interface[0].altsetting[0].bInterfaceSubClass == 0x06) + && (dev->config[0].interface[0].altsetting[0].bInterfaceProtocol == 0x50) ) { + debug ("Found modem mass storage device '%s'", dev->filename); + return dev; + } + } + } + } + return NULL; +} + +static int +find_endpoints (struct usb_device *dev, int *in_ep, int *out_ep) +{ + int i; + + for (i = 0; i < dev->config[0].interface[0].altsetting[0].bNumEndpoints; i++) { + struct usb_endpoint_descriptor *ep = &(dev->config[0].interface[0].altsetting[0].endpoint[i]); + + if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { + unsigned int direction = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; + + if (!*out_ep && (direction == USB_DIR_OUT)) + *out_ep = ep->bEndpointAddress; + else if (!*in_ep && (direction == USB_DIR_IN)) + *in_ep = ep->bEndpointAddress; + } + + if (*in_ep && *out_ep) + return 0; + } + + return -1; +} + +int +option_zerocd_switch (struct usb_dev_handle *dh, struct usb_device *dev) +{ + const char const rezero_cbw[] = { + 0x55, 0x53, 0x42, 0x43, /* bulk command signature (LE) */ + 0x78, 0x56, 0x34, 0x12, /* bulk command host tag */ + 0x01, 0x00, 0x00, 0x00, /* bulk command data transfer length (LE) */ + 0x80, /* flags: direction data-in */ + 0x00, /* LUN */ + 0x06, /* SCSI command length */ + 0x01, /* SCSI command: REZERO */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* filler */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + int ret = -1, ep_in = 0, ep_out = 0; + char buffer[256]; + + /* Find the device's bulk in and out endpoints */ + if (find_endpoints (dev, &ep_in, &ep_out) < 0) { + debug ("%s: couldn't find correct USB endpoints.", dev->filename); + goto out; + } + + usb_clear_halt (dh, ep_out); + ret = usb_set_altinterface (dh, 0); + if (ret != 0) { + debug ("%s: couldn't set device alternate interface.", dev->filename); + goto out; + } + + /* Let the mass storage device settle */ + sleep (1); + + /* Send the modeswitch command */ + ret = usb_bulk_write (dh, ep_out, (char *) rezero_cbw, sizeof (rezero_cbw), 1000); + if (ret < 0) + return ret; + + debug ("%s: REZERO command sent.", dev->filename); + + /* Some devices need to be read from */ + ret = usb_bulk_read (dh, ep_in, buffer, sizeof (buffer), 1000); + +out: + return ret; +} + diff --git a/modem-modeswitch/option.h b/modem-modeswitch/option.h new file mode 100644 index 0000000..e00dabf --- /dev/null +++ b/modem-modeswitch/option.h @@ -0,0 +1,29 @@ +/* + * Modem mode switcher + * + * Copyright (C) 2008 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: + */ + +#ifndef __OPTION_H__ +#define __OPTION_H__ + +#include <usb.h> + +struct usb_device *option_zerocd_find (int vid, int pid); + +int option_zerocd_switch (struct usb_dev_handle *dh, struct usb_device *dev); + +#endif /* __OPTION_H__ */ diff --git a/modem-modeswitch/utils.c b/modem-modeswitch/utils.c new file mode 100644 index 0000000..37d0df4 --- /dev/null +++ b/modem-modeswitch/utils.c @@ -0,0 +1,83 @@ +/* + * Modem mode switcher + * + * Copyright (C) 2009 Dan Williams <dcbw@redhat.com> + * + * 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 <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> + +#include "utils.h" + +static int debug_on = 0; +static int quiet = 0; +FILE *logfile = NULL; + +void +do_log (int level, const char *fmt, ...) +{ + va_list args; + char buffer[1024]; + char tag = 'L'; + + if (level >= LOG_DBG && !debug_on) + return; + + va_start (args, fmt); + vsnprintf (buffer, sizeof (buffer), fmt, args); + va_end (args); + + if (level == LOG_ERR) + tag = 'E'; + else if (level == LOG_MSG) + tag = 'L'; + else if (level == LOG_DBG) + tag = 'D'; + + if (logfile) + fprintf (logfile, "%c: %s\n", tag, buffer); + if (!quiet) + fprintf ((level == LOG_ERR) ? stderr : stdout, "%c: %s\n", tag, buffer); +} + +int +log_startup (const char *path, int do_debug, int be_quiet) +{ + time_t t; + + quiet = be_quiet; + debug_on = do_debug; + + if (!path) + return 0; + + logfile = fopen (path, "a+"); + if (!logfile) + return 1; + + t = time (NULL); + message ("\n**** Started: %s\n", ctime (&t)); + return 0; +} + +void +log_shutdown (void) +{ + if (logfile) + fclose (logfile); +} + diff --git a/modem-modeswitch/utils.h b/modem-modeswitch/utils.h new file mode 100644 index 0000000..1ef557a --- /dev/null +++ b/modem-modeswitch/utils.h @@ -0,0 +1,32 @@ +/* + * Modem mode switcher + * + * Copyright (C) 2009 Dan Williams <dcbw@redhat.com> + * + * 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: + */ + +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#define LOG_ERR 0 +#define LOG_MSG 1 +#define LOG_DBG 2 + +#define message(fmt, args...) do_log (LOG_MSG, fmt, ##args); +#define error(fmt, args...) do_log (LOG_ERR, fmt, ##args); +#define debug(fmt, args...) do_log (LOG_DBG, fmt, ##args); + +void do_log (int level, const char *fmt, ...); +int log_startup (const char *path, int do_debug, int be_quiet); +void log_shutdown (void); + +#endif /* __UTILS_H__ */ |