mirror of
https://github.com/systemd/systemd.git
synced 2025-01-26 14:04:03 +03:00
extras/modem-modeswitch: move from udev-extras
This commit is contained in:
parent
0fb7c51846
commit
181368a3b2
@ -125,6 +125,7 @@ AC_CONFIG_FILES([
|
||||
extras/gudev/docs/Makefile
|
||||
extras/gudev/docs/version.xml
|
||||
extras/keymap/Makefile
|
||||
extras/modem-modeswitch/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
|
@ -20,5 +20,6 @@ SUBDIRS += \
|
||||
usb-db \
|
||||
hid2hci \
|
||||
keymap \
|
||||
modem-modeswitch \
|
||||
gudev
|
||||
endif
|
||||
|
1
extras/modem-modeswitch/.gitignore
vendored
Normal file
1
extras/modem-modeswitch/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
modem-modeswitch
|
9
extras/modem-modeswitch/61-mobile-action.rules
Normal file
9
extras/modem-modeswitch/61-mobile-action.rules
Normal file
@ -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"
|
38
extras/modem-modeswitch/61-option-modem-modeswitch.rules
Normal file
38
extras/modem-modeswitch/61-option-modem-modeswitch.rules
Normal file
@ -0,0 +1,38 @@
|
||||
ACTION!="add", GOTO="option_zerocd_end"
|
||||
|
||||
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"
|
||||
|
||||
LABEL="option_zerocd_disable"
|
||||
ATTRS{idVendor}=="05c6", ATTRS{idProduct}=="1000", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6711", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6711", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6731", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6751", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6771", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6791", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6811", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6911", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6951", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="6971", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7011", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7031", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7051", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7071", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7111", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7211", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7251", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7271", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7311", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="c031", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="d031", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="d033", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7301", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7361", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7401", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7501", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7601", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
ATTRS{idVendor}=="0af0", ATTRS{idProduct}=="7901", RUN+="modem-modeswitch -v 0x%s{idVendor} -p 0x%s{idProduct} -t option-zerocd"
|
||||
|
||||
LABEL="option_zerocd_end"
|
26
extras/modem-modeswitch/Makefile.am
Normal file
26
extras/modem-modeswitch/Makefile.am
Normal file
@ -0,0 +1,26 @@
|
||||
include $(top_srcdir)/Makefile.am.inc
|
||||
|
||||
libexec_PROGRAMS = \
|
||||
modem-modeswitch
|
||||
|
||||
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)
|
||||
|
||||
dist_udevrules_DATA = \
|
||||
61-option-modem-modeswitch.rules \
|
||||
61-mobile-action.rules
|
||||
|
||||
dist_man_MANS = \
|
||||
modem-modeswitch.8
|
454
extras/modem-modeswitch/ma8280p_us.c
Normal file
454
extras/modem-modeswitch/ma8280p_us.c
Normal file
@ -0,0 +1,454 @@
|
||||
/* 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);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (buf)
|
||||
free (buf);
|
||||
return 0;
|
||||
}
|
24
extras/modem-modeswitch/ma8280p_us.h
Normal file
24
extras/modem-modeswitch/ma8280p_us.h
Normal file
@ -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__ */
|
39
extras/modem-modeswitch/modem-modeswitch.8
Normal file
39
extras/modem-modeswitch/modem-modeswitch.8
Normal file
@ -0,0 +1,39 @@
|
||||
.TH MODEM_MODESWITCH 8 "November 2005" "" "Linux Administrator's Manual"
|
||||
.SH NAME
|
||||
modem-modeswitch \- udev callout to switch mobile broadband devices to their
|
||||
intended modem mode
|
||||
.SH SYNOPSIS
|
||||
.BI modem-modeswitch
|
||||
\fI--vendor <vendor id>\fP \fI--product <product id>\fP [\fI--debug\fP]
|
||||
\fI--type <type>\fP \fI<devpath>\fP
|
||||
.SH "DESCRIPTION"
|
||||
.B modem-modeswitch
|
||||
is normally called from a udev rule, to eject the driver CD that many mobile
|
||||
broadband devices mount by default, and switch them into modem mode.
|
||||
.SH USAGE
|
||||
.B modem-modeswitch
|
||||
switches the device into modem mode
|
||||
.SH OPTIONS
|
||||
The following commandline switches are supported:
|
||||
.TP
|
||||
.BI \-\-vendor\ <vid>
|
||||
the USB vendor ID of the mobile broadband device to switch
|
||||
.TP
|
||||
.BI \-\-product\ <pid>
|
||||
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, mobile-action-8280p)
|
||||
.TP
|
||||
.BI \-\-log\ <file>
|
||||
log verbose debugging information about the switching process
|
||||
.TP
|
||||
.BI \-\-debug
|
||||
print verbose debugging information about the switching process
|
||||
.RE
|
||||
.SH SEE ALSO
|
||||
.BR udev (7)
|
||||
.SH AUTHORS
|
||||
Developed by Dan Williams <dcbw@redhat.com> based off code by Peter Henn
|
||||
<p.henn@option.com>.
|
||||
|
266
extras/modem-modeswitch/modem-modeswitch.c
Normal file
266
extras/modem-modeswitch/modem-modeswitch.c
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* 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 <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"
|
||||
#include "option.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_OPTION_ZEROCD,
|
||||
ST_MA8280P
|
||||
} SwitchType;
|
||||
|
||||
typedef struct SwitchEntry {
|
||||
SwitchType st;
|
||||
const char *clopt;
|
||||
FindFunc find_func;
|
||||
SwitchFunc switch_func;
|
||||
} SwitchEntry;
|
||||
|
||||
static SwitchEntry switch_types[] = {
|
||||
{ ST_OPTION_ZEROCD, "option-zerocd", option_zerocd_find, option_zerocd_switch },
|
||||
{ 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: modem-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"
|
||||
" 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"
|
||||
"Examples:\n"
|
||||
" modem-modeswitch -v 0x0af0 -p 0xc031 -t option-zerocd\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 modem 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;
|
||||
}
|
131
extras/modem-modeswitch/option.c
Normal file
131
extras/modem-modeswitch/option.c
Normal file
@ -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;
|
||||
}
|
||||
|
29
extras/modem-modeswitch/option.h
Normal file
29
extras/modem-modeswitch/option.h
Normal file
@ -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__ */
|
83
extras/modem-modeswitch/utils.c
Normal file
83
extras/modem-modeswitch/utils.c
Normal file
@ -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);
|
||||
}
|
||||
|
32
extras/modem-modeswitch/utils.h
Normal file
32
extras/modem-modeswitch/utils.h
Normal file
@ -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__ */
|
Loading…
x
Reference in New Issue
Block a user