Problem adding a new device using an initializer

Rui Santos <[email protected]>
Newsgroups gmane.linux.usb.devel
Organization GrupoPIE, Portugal SA
Message-ID <[email protected]>
Hi all,

I currently own a USB 3G mobile device manufactured under the name ZTE
MF620.
At the same time I also own a Huawei USB E220 device.

On 2.6.24-rc5, the Huawei device uses an initializer to switch the
device from a usb-storage to a multi-port mode, that was previously
being done by a userspace application.
I was trying to do the same with the ZTE device, but I'm getting
frustrated. This same ZTE device has a userspace application that also
switches it to a multi-port mode.
Can anyone tell me what I'm doing wrong ?

This is the userspace program ( includes libusb ):
/* This file is 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>
#if 0
 #include <linux/usbdevice_fs.h>
 #define LIBUSB_AUGMENT
 #include "libusb_augment.h"
#endif

struct usb_dev_handle *devh;

void release_usb_device(int dummy) {
    int ret;
    ret = usb_release_interface(devh, 0);
    if (!ret)
    printf("failed to release interface: %d\n", ret);
    usb_close(devh);
    if (!ret)
    printf("failed to close interface: %d\n", ret);
    exit(1);
}

void list_devices() {
    struct usb_bus *bus;
    for (bus = usb_get_busses(); bus; bus = bus->next) {
    struct usb_device *dev;

    for (dev = bus->devices; dev; dev = dev->next)
        printf("0x%04x 0x%04x\n",
           dev->descriptor.idVendor,
           dev->descriptor.idProduct);
    }
}

struct usb_device *find_device(int vendor, int product) {
    struct usb_bus *bus;

    for (bus = usb_get_busses(); bus; bus = bus->next) {
    struct usb_device *dev;

    for (dev = bus->devices; dev; dev = dev->next) {
        if (dev->descriptor.idVendor == vendor
        && dev->descriptor.idProduct == product)
        return dev;
    }
    }
    return NULL;
}

void print_bytes(char *bytes, int len) {
    int i;
    if (len > 0) {
    for (i=0; i<len; i++) {
        printf("%02x ", (int)((unsigned char)bytes[i]));
    }
    printf("\"");
        for (i=0; i<len; i++) {
        printf("%c", isprint(bytes[i]) ? bytes[i] : '.');
        }
        printf("\"");
    }
}


int main(int argc, char **argv) {
    int ret, vendor, product;
    struct usb_device *dev;
    char buf[65536], *endptr;
#if 0
    usb_urb *isourb;
    struct timeval isotv;
    char isobuf[32768];
#endif

    sleep(5);

    usb_init();
    usb_set_debug(255);
    usb_find_busses();
    usb_find_devices();

/*    if (argc!=3) {
    printf("usage: %s vendorID productID\n", argv[0]);
    printf("ID numbers of currently attached devices:\n");
    list_devices();
    exit(1);
    }
    vendor = strtol(argv[1], &endptr, 16);
    if (*endptr != '\0') {
    printf("invalid vendor id\n");
    exit(1);
    }
    product = strtol(argv[2], &endptr, 16);
    if (*endptr != '\0') {
    printf("invalid product id\n");
    exit(1);
    }*/

    /* printf("ZTE MF620 USB modem\n"); */
    vendor = 0x19d2;
    product = 0x2000;
    dev = find_device(vendor, product);
    assert(dev);

    devh = usb_open(dev);
    assert(devh);

    signal(SIGTERM, release_usb_device);

    ret = usb_get_driver_np(devh, 0, buf, sizeof(buf));
    /* printf("usb_get_driver_np returned %d\n", ret); */
    if (ret == 0) {
    /* printf("interface 0 already claimed by driver \"%s\", attempting
to detach it\n", buf); */
    ret = usb_detach_kernel_driver_np(devh, 0);
    /* printf("usb_detach_kernel_driver_np returned %d\n", ret); */
    }
    ret = usb_claim_interface(devh, 0);
    if (ret != 0) {
    /* printf("claim failed with error %d\n", ret); */
        exit(1);
    }

    ret = usb_set_altinterface(devh, 0);
    assert(ret >= 0);

ret = usb_get_descriptor(devh, 0x0000001, 0x0000000, buf, 0x0000012);
/* printf("1 get descriptor returned %d, bytes: ", ret); */
print_bytes(buf, ret);
/* printf("\n"); */
usleep(4*1000);
ret = usb_get_descriptor(devh, 0x0000002, 0x0000000, buf, 0x0000009);
/* printf("2 get descriptor returned %d, bytes: ", ret); */
print_bytes(buf, ret);
/* printf("\n"); */
usleep(4*1000);
ret = usb_get_descriptor(devh, 0x0000002, 0x0000000, buf, 0x0000020);
/* printf("3 get descriptor returned %d, bytes: ", ret); */
print_bytes(buf, ret);
/* printf("\n"); */
usleep(4*1000);
ret = usb_release_interface(devh, 0);
/* if (ret != 0) printf("failed to release interface before
set_configuration: %d\n", ret); */
ret = usb_set_configuration(devh, 0x0000001);
/* printf("4 set configuration returned %d\n", ret); */
ret = usb_claim_interface(devh, 0);
if (ret != 0) printf("claim after set_configuration failed with error
%d\n", ret);
ret = usb_set_altinterface(devh, 0);
/* printf("4 set alternate setting returned %d\n", ret); */
usleep(63*1000);
ret = usb_set_altinterface(devh, 0);
/* printf("5 set alternate setting returned %d\n", ret); */
usleep(62*1000);
ret = usb_control_msg(devh, USB_TYPE_CLASS + USB_RECIP_INTERFACE +
USB_ENDPOINT_IN, 0x00000fe, 0x0000000, 0x0000000, buf, 0x0000001, 1000);
/* printf("6 control msg returned %d, bytes: ", ret); */
print_bytes(buf, ret);
/* printf("\n"); */
usleep(4*1000);

/*memcpy(buf,
"\x55\x53\x42\x43\xe8\x48\xef\x81\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
0x000001f);
ret = usb_bulk_write(devh, 0x00000004, buf, 0x000001f, 1000);
printf("548 bulk write returned %d, bytes: ", ret);
print_bytes(buf, ret);
printf("\n");
usleep(2*1000);
ret = usb_bulk_read(devh, 0x00000083, buf, 0x000000d, 1000);
printf("549 bulk read returned %d, bytes: ", ret);
print_bytes(buf, ret);
printf("\n");
usleep(3*1000);*/

memcpy(buf,
"\x55\x53\x42\x43\x08\xf0\x10\x82\x00\x00\x00\x00\x00\x00\x0a\x85\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00",
0x000001f);
ret = usb_bulk_write(devh, 0x00000004, buf, 0x000001f, 1000);
/* printf("550 bulk write returned %d, bytes: ", ret); */
print_bytes(buf, ret);
/* printf("\n"); */
usleep(1*1000);
ret = usb_bulk_read(devh, 0x00000083, buf, 0x000000d, 1000);
/* printf("551 bulk read returned %d, bytes: ", ret); */
print_bytes(buf, ret);
/* printf("\n"); */
usleep(2*1000);

usb_resetep(devh, 0x83);

ret = usb_release_interface(devh, 0);
assert(ret == 0);
ret = usb_close(devh);
assert(ret == 0);
return 0;
}

This is the Kernel initializer I'm trying to add at
drivers/usb/storage/initializers.c that is not working:

int usb_stor_zte_mf620_init(struct us_data *us)
{
    int result;

    us->iobuf[0] = 0x1;
    result = usb_stor_control_msg(us, us->send_ctrl_pipe,
                      0xFE,
                      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
                      0x0, 0x0, us->iobuf, 0x1, 1000);
    US_DEBUGP("usb_control_msg performing result is %d\n", result);
    msleep(4);
    memcpy(us->iobuf, "\x55\x53\x42\x43\x08\xf0\x10\x82\x00\x00\x00\x00"
                      "\x00\x00\x0a\x85\x01\x01\x01\x01\x01\x01\x01\x01"
                      "\x01\x00\x00\x00\x00\x00\x00", 0x1F);
    usb_stor_bulk_transfer_buf(us, us->send_ctrl_pipe, us->iobuf, 0x1F,
NULL);
    usb_stor_Bulk_reset(us);
    return (result ? 0 : -1);

This is also placed at drivers/usb/storage/unusual_devs.h :

UNUSUAL_DEV( 0x19d2, 0x2000, 0x0000, 0x0000,
        "Qualcomm ZTE MF620",
        "Mass Storage",
        US_SC_DEVICE, US_PR_DEVICE, usb_stor_zte_mf620_init,
        0),


NOTE: In order for userspace application to succeed in changing the ZTE
to multi-port mode, it has to be called before the USB device finishes
to "settle".

Thanks for your help,
Rui Santos


-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.