#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <libusb-1.0.h>





struct libusb_device * find_devs(struct libusb_device **devs, uint16_t ivendor);

void list_devs(struct libusb_device **devs);

void fGet_device_status(struct libusb_device *adevice, struct libusb_device_handle *adevice_handle);



int main (int argc,char **argv)

{

    //先宣告Device Handle 與Device Struct

    struct libusb_device_handle *iPod_device_handle;

    struct libusb_device *iPod_device;



    int open_status=-1;

    int func_status=-1;

    int intf_status=-1;

    int interface;



    unsigned char send_data=0xff;

    unsigned char receive_data=0;

    unsigned char CtrlOut;

    unsigned char CtrlIn;



    libusb_device **devs;

    ssize_t cnt;

    unsigned char data[500];

    int actual_length=0;

    int r;



    int i=0,ack=0;

    int TotalConfig=-1,LockConfig=-1;

    int TotalInter=-1,LockInter=-1;



    char mailo[64];









    //USB初始化動作,設置訊息等級

    {

        ack=libusb_init(NULL);

        if(ack==0)

            printf("(1)Init....................Done\r\n");

        else

            printf("(1)Init....................Error(%d)\r\n",ack);

        libusb_set_debug(NULL,3);

    }



    //回傳連接USB的device個數, 並把資料放到第二個參數指標內

    {

        ack=libusb_get_device_list(NULL, &devs);

        if(ack>=0)

            printf("(2)Got Devices=%d...........Done\r\n",ack);

        else

        {

            printf("(2)Got Devices.............Error(%d)\r\n",ack);

            return (int) cnt;

        }

    }



    //因為libusb_device是個lib沒有釋出結構的指標, 必須換成libusb_device_descriptor這個有定義的東西秀出來

    list_devs(devs);



    //比對VID碼

    {

        //Sicon USB:    0x0457

        //RS232 bard:   0x067b

        iPod_device=find_devs(devs, 0x067b);

        if(iPod_device>0)

            printf("(3)Got Apple...............Done\r\n");

        else

            printf("(3)Got Apple...............Error(%d)\r\n",ack);

    }



    if(iPod_device>0)

    {

        //這裡是使用libusb_device指標打開, 並且第二個參數是拿來回傳存放結構的指標

        {

            open_status=libusb_open(iPod_device, &iPod_device_handle);

            if(open_status==0)

                printf("(4)Open Device.............Done\r\n",ack);

            else

                printf("(4)Open Device.............Error(%d)\r\n",ack);

        }



        if(open_status==0)//success

        {

            //讀取目前config數量

            {

                ack=libusb_control_transfer

                        (iPod_device_handle,

                         LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_DEVICE,

                         LIBUSB_REQUEST_GET_DESCRIPTOR,

                         LIBUSB_DT_DEVICE<<8|0,

                         0,

                         data,

                         500,

                         1000

                        );

                TotalConfig=data[17];

                if(ack==18)

                    printf("(5)Total Config=%d..........Done\r\n",TotalConfig);

                else

                    printf("(5)Total Config............Error(%d)\r\n",ack);



            }



            //偵測OS是否占用目前鎖定config裡的interface

            {

                //這裡的config從1開始算, 跟control_transfer的偏移量不同

                ack=libusb_get_configuration(iPod_device_handle, &LockConfig);

                if(ack==0)

                    printf("(5)Lock Config=%d...........Done\r\n",LockConfig);

                else

                    printf("(5)Lock Config.............Error(%d)\r\n",ack);





                ack=libusb_control_transfer

                        (iPod_device_handle,

                         LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_DEVICE,

                         LIBUSB_REQUEST_GET_DESCRIPTOR,

                         LIBUSB_DT_CONFIG<<8|(LockConfig-1),

                         0,

                         data,

                         500,

                         1000

                        );

                TotalInter=data[4];

                printf("(6)Total Interface=%d.......Done\r\n",TotalInter);



                for(i=0;i<TotalInter;i++)

                {

                    ack=libusb_kernel_driver_active(iPod_device_handle,i);

                    printf("(6)OS toke Interface%d......Done(%d)\r\n",i,ack);

                    if(ack==1)

                    {   //關閉OS對這interface的使用

                        func_status=libusb_detach_kernel_driver(iPod_device_handle, i);

                        LockInter=i;

                    }

                }

            }



            //設定這個configration為alive

            {

                i=LockConfig;

                ack=libusb_set_configuration(iPod_device_handle,i);

                if(ack==0)

                    printf("(7)Set LockConfig=%d........Done\r\n",i);

                else

                    printf("(7)Set LockConfig..........Error(%d)\r\n",ack);

            }



            //申請這個介面為alive

            if(LockInter!=-1)

            {

                i=LockInter;

                intf_status=libusb_claim_interface(iPod_device_handle,i);

                if(intf_status==0)

                    printf("(7)Set LockInter=%d.........Done\r\n",i);

                else

                    printf("(7)Set LockInter...........Error(%d)\r\n",ack);

            }



            memset(data,0x00,sizeof(data));

            strcpy(data,"cd //home");

            data[8]=0xD;



            ack=libusb_bulk_transfer

                    (iPod_device_handle,

                     2,

                     data,

                     9,

                     &actual_length

                     ,1000

                     );

            printf("ack=%d,data tarnslen=%d\r\n",ack,actual_length);

        }

        else

            return -1;

    }





    libusb_free_device_list(devs, 1);





    if(intf_status==0)

    {

        func_status = libusb_release_interface(iPod_device_handle, interface);

        printf("release_interface %d status=%d\n",interface,func_status);

    }



    if(open_status==0)

    {

        libusb_close(iPod_device_handle);

        printf("close_handle\n");



    }



    libusb_exit(NULL);





}



void fGet_device_status(struct libusb_device *dev, struct libusb_device_handle *dev_handle)

{

    int r;

    struct libusb_device_descriptor desc;

    struct libusb_config_descriptor *config,*config2,*config3;

    int index;

    unsigned char atempstring[200];

    int i;



    r = libusb_get_device_descriptor(dev, &desc);

    printf("device_descriptor status=%d\n",r);



    r = libusb_get_active_config_descriptor(dev, &config);

    printf("get_active_config_descriptor status=%d\n",r);



    index=0;

    r = libusb_get_config_descriptor(dev, index, &config2);

    printf("get_config_descriptor %d status=%d\n", index, r);



    index=1;

    r = libusb_get_config_descriptor_by_value(dev, index, &config3);

    printf("get_config_descriptor_byValue %d status=%d\n", index, r);



    for(i=1;i<5;i++)

    {

        memset(atempstring, 0, 200);

        r=libusb_get_string_descriptor_ascii(dev_handle, i, atempstring, 200 );

        printf("get_cstring_descriptor %d _ascii \"%s\" len=%d\n", i, atempstring, r);

    }



    for(i=1;i<5;i++)

    {

        memset(atempstring, 0, 200);

        r=libusb_get_descriptor(dev_handle, LIBUSB_DT_DEVICE, i, atempstring, 200 );

        printf("get_cstring_descriptor %d len=%d\n", i, r);

    }



    for(i=1;i<5;i++)

    {

        memset(atempstring, 0, 200);

        r=libusb_get_descriptor(dev_handle, LIBUSB_DT_INTERFACE, i, atempstring, 200 );

        printf("get_cstring_descriptor %d len=%d\n", i, r);

    }



    libusb_free_config_descriptor(config);

    printf("free_config_descriptor");

    libusb_free_config_descriptor(config2);

    printf("free_config_descriptor");

    libusb_free_config_descriptor(config3);

    printf("free_config_descriptor");

    return;

}



struct libusb_device * find_devs(struct libusb_device **devs, uint16_t ivendor)

{

    struct libusb_device *dev;

    struct libusb_device_descriptor desc;

    int i=0,r=0;



    while((dev=devs[i++])!=NULL)

    {

        r=libusb_get_device_descriptor(dev, &desc);

        if(r < 0)

        {

            fprintf(stderr, "failed to get device descriptor");

        }

        else

        {

            if(desc.idVendor==ivendor)

                return dev;

        }

    }

    return 0;

}



void list_devs(struct libusb_device **devs)

{

    struct libusb_device *dev;

    struct libusb_device_descriptor desc;

    int i=0,r=0;



    while((dev=devs[i++])!=NULL)

    {

        r=libusb_get_device_descriptor(dev, &desc);

        if(r<0)

        {

            fprintf(stderr, "failed to get device descriptor");

            