#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");
I2luY2x1ZGUgPHN0ZGlvLmg+CgojaW5jbHVkZSA8c3RyaW5nLmg+CgojaW5jbHVkZSA8c3lzL3R5cGVzLmg+CgojaW5jbHVkZSA8bGlidXNiLTEuMC5oPgoKCgoKCnN0cnVjdCBsaWJ1c2JfZGV2aWNlICogZmluZF9kZXZzKHN0cnVjdCBsaWJ1c2JfZGV2aWNlICoqZGV2cywgdWludDE2X3QgaXZlbmRvcik7Cgp2b2lkIGxpc3RfZGV2cyhzdHJ1Y3QgbGlidXNiX2RldmljZSAqKmRldnMpOwoKdm9pZCBmR2V0X2RldmljZV9zdGF0dXMoc3RydWN0IGxpYnVzYl9kZXZpY2UgKmFkZXZpY2UsIHN0cnVjdCBsaWJ1c2JfZGV2aWNlX2hhbmRsZSAqYWRldmljZV9oYW5kbGUpOwoKCgppbnQgbWFpbiAoaW50IGFyZ2MsY2hhciAqKmFyZ3YpCgp7CgogICAgLy/lhYjlrqPlkYpEZXZpY2UgSGFuZGxlIOiIh0RldmljZSBTdHJ1Y3QKCiAgICBzdHJ1Y3QgbGlidXNiX2RldmljZV9oYW5kbGUgKmlQb2RfZGV2aWNlX2hhbmRsZTsKCiAgICBzdHJ1Y3QgbGlidXNiX2RldmljZSAqaVBvZF9kZXZpY2U7CgoKCiAgICBpbnQgb3Blbl9zdGF0dXM9LTE7CgogICAgaW50IGZ1bmNfc3RhdHVzPS0xOwoKICAgIGludCBpbnRmX3N0YXR1cz0tMTsKCiAgICBpbnQgaW50ZXJmYWNlOwoKCgogICAgdW5zaWduZWQgY2hhciBzZW5kX2RhdGE9MHhmZjsKCiAgICB1bnNpZ25lZCBjaGFyIHJlY2VpdmVfZGF0YT0wOwoKICAgIHVuc2lnbmVkIGNoYXIgQ3RybE91dDsKCiAgICB1bnNpZ25lZCBjaGFyIEN0cmxJbjsKCgoKICAgIGxpYnVzYl9kZXZpY2UgKipkZXZzOwoKICAgIHNzaXplX3QgY250OwoKICAgIHVuc2lnbmVkIGNoYXIgZGF0YVs1MDBdOwoKICAgIGludCBhY3R1YWxfbGVuZ3RoPTA7CgogICAgaW50IHI7CgoKCiAgICBpbnQgaT0wLGFjaz0wOwoKICAgIGludCBUb3RhbENvbmZpZz0tMSxMb2NrQ29uZmlnPS0xOwoKICAgIGludCBUb3RhbEludGVyPS0xLExvY2tJbnRlcj0tMTsKCgoKICAgIGNoYXIgbWFpbG9bNjRdOwoKCgoKCgoKCgogICAgLy9VU0LliJ3lp4vljJbli5XkvZws6Kit572u6KiK5oGv562J57SaCgogICAgewoKICAgICAgICBhY2s9bGlidXNiX2luaXQoTlVMTCk7CgogICAgICAgIGlmKGFjaz09MCkKCiAgICAgICAgICAgIHByaW50ZigiKDEpSW5pdC4uLi4uLi4uLi4uLi4uLi4uLi4uRG9uZVxyXG4iKTsKCiAgICAgICAgZWxzZQoKICAgICAgICAgICAgcHJpbnRmKCIoMSlJbml0Li4uLi4uLi4uLi4uLi4uLi4uLi5FcnJvciglZClcclxuIixhY2spOwoKICAgICAgICBsaWJ1c2Jfc2V0X2RlYnVnKE5VTEwsMyk7CgogICAgfQoKCgogICAgLy/lm57lgrPpgKPmjqVVU0LnmoRkZXZpY2XlgIvmlbgsIOS4puaKiuizh+aWmeaUvuWIsOesrOS6jOWAi+WPg+aVuOaMh+aomeWFpwoKICAgIHsKCiAgICAgICAgYWNrPWxpYnVzYl9nZXRfZGV2aWNlX2xpc3QoTlVMTCwgJmRldnMpOwoKICAgICAgICBpZihhY2s+PTApCgogICAgICAgICAgICBwcmludGYoIigyKUdvdCBEZXZpY2VzPSVkLi4uLi4uLi4uLi5Eb25lXHJcbiIsYWNrKTsKCiAgICAgICAgZWxzZQoKICAgICAgICB7CgogICAgICAgICAgICBwcmludGYoIigyKUdvdCBEZXZpY2VzLi4uLi4uLi4uLi4uLkVycm9yKCVkKVxyXG4iLGFjayk7CgogICAgICAgICAgICByZXR1cm4gKGludCkgY250OwoKICAgICAgICB9CgogICAgfQoKCgogICAgLy/lm6DngrpsaWJ1c2JfZGV2aWNl5piv5YCLbGli5rKS5pyJ6YeL5Ye657WQ5qeL55qE5oyH5qiZLCDlv4XpoIjmj5vmiJBsaWJ1c2JfZGV2aWNlX2Rlc2NyaXB0b3LpgJnlgIvmnInlrprnvqnnmoTmnbHopb/np4Dlh7rkvoYKCiAgICBsaXN0X2RldnMoZGV2cyk7CgoKCiAgICAvL+avlOWwjVZJROeivAoKICAgIHsKCiAgICAgICAgLy9TaWNvbiBVU0I6ICAgIDB4MDQ1NwoKICAgICAgICAvL1JTMjMyIGJhcmQ6ICAgMHgwNjdiCgogICAgICAgIGlQb2RfZGV2aWNlPWZpbmRfZGV2cyhkZXZzLCAweDA2N2IpOwoKICAgICAgICBpZihpUG9kX2RldmljZT4wKQoKICAgICAgICAgICAgcHJpbnRmKCIoMylHb3QgQXBwbGUuLi4uLi4uLi4uLi4uLi5Eb25lXHJcbiIpOwoKICAgICAgICBlbHNlCgogICAgICAgICAgICBwcmludGYoIigzKUdvdCBBcHBsZS4uLi4uLi4uLi4uLi4uLkVycm9yKCVkKVxyXG4iLGFjayk7CgogICAgfQoKCgogICAgaWYoaVBvZF9kZXZpY2U+MCkKCiAgICB7CgogICAgICAgIC8v6YCZ6KOh5piv5L2/55SobGlidXNiX2RldmljZeaMh+aomeaJk+mWiywg5Lim5LiU56ys5LqM5YCL5Y+D5pW45piv5ou/5L6G5Zue5YKz5a2Y5pS+57WQ5qeL55qE5oyH5qiZCgogICAgICAgIHsKCiAgICAgICAgICAgIG9wZW5fc3RhdHVzPWxpYnVzYl9vcGVuKGlQb2RfZGV2aWNlLCAmaVBvZF9kZXZpY2VfaGFuZGxlKTsKCiAgICAgICAgICAgIGlmKG9wZW5fc3RhdHVzPT0wKQoKICAgICAgICAgICAgICAgIHByaW50ZigiKDQpT3BlbiBEZXZpY2UuLi4uLi4uLi4uLi4uRG9uZVxyXG4iLGFjayk7CgogICAgICAgICAgICBlbHNlCgogICAgICAgICAgICAgICAgcHJpbnRmKCIoNClPcGVuIERldmljZS4uLi4uLi4uLi4uLi5FcnJvciglZClcclxuIixhY2spOwoKICAgICAgICB9CgoKCiAgICAgICAgaWYob3Blbl9zdGF0dXM9PTApLy9zdWNjZXNzCgogICAgICAgIHsKCiAgICAgICAgICAgIC8v6K6A5Y+W55uu5YmNY29uZmln5pW46YePCgogICAgICAgICAgICB7CgogICAgICAgICAgICAgICAgYWNrPWxpYnVzYl9jb250cm9sX3RyYW5zZmVyCgogICAgICAgICAgICAgICAgICAgICAgICAoaVBvZF9kZXZpY2VfaGFuZGxlLAoKICAgICAgICAgICAgICAgICAgICAgICAgIExJQlVTQl9FTkRQT0lOVF9JTnxMSUJVU0JfUkVDSVBJRU5UX0RFVklDRSwKCiAgICAgICAgICAgICAgICAgICAgICAgICBMSUJVU0JfUkVRVUVTVF9HRVRfREVTQ1JJUFRPUiwKCiAgICAgICAgICAgICAgICAgICAgICAgICBMSUJVU0JfRFRfREVWSUNFPDw4fDAsCgogICAgICAgICAgICAgICAgICAgICAgICAgMCwKCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLAoKICAgICAgICAgICAgICAgICAgICAgICAgIDUwMCwKCiAgICAgICAgICAgICAgICAgICAgICAgICAxMDAwCgogICAgICAgICAgICAgICAgICAgICAgICApOwoKICAgICAgICAgICAgICAgIFRvdGFsQ29uZmlnPWRhdGFbMTddOwoKICAgICAgICAgICAgICAgIGlmKGFjaz09MTgpCgogICAgICAgICAgICAgICAgICAgIHByaW50ZigiKDUpVG90YWwgQ29uZmlnPSVkLi4uLi4uLi4uLkRvbmVcclxuIixUb3RhbENvbmZpZyk7CgogICAgICAgICAgICAgICAgZWxzZQoKICAgICAgICAgICAgICAgICAgICBwcmludGYoIig1KVRvdGFsIENvbmZpZy4uLi4uLi4uLi4uLkVycm9yKCVkKVxyXG4iLGFjayk7CgoKCiAgICAgICAgICAgIH0KCgoKICAgICAgICAgICAgLy/lgbXmuKxPU+aYr+WQpuWNoOeUqOebruWJjemOluWummNvbmZpZ+ijoeeahGludGVyZmFjZQoKICAgICAgICAgICAgewoKICAgICAgICAgICAgICAgIC8v6YCZ6KOh55qEY29uZmln5b6eMemWi+Wni+eulywg6LefY29udHJvbF90cmFuc2ZlcueahOWBj+enu+mHj+S4jeWQjAoKICAgICAgICAgICAgICAgIGFjaz1saWJ1c2JfZ2V0X2NvbmZpZ3VyYXRpb24oaVBvZF9kZXZpY2VfaGFuZGxlLCAmTG9ja0NvbmZpZyk7CgogICAgICAgICAgICAgICAgaWYoYWNrPT0wKQoKICAgICAgICAgICAgICAgICAgICBwcmludGYoIig1KUxvY2sgQ29uZmlnPSVkLi4uLi4uLi4uLi5Eb25lXHJcbiIsTG9ja0NvbmZpZyk7CgogICAgICAgICAgICAgICAgZWxzZQoKICAgICAgICAgICAgICAgICAgICBwcmludGYoIig1KUxvY2sgQ29uZmlnLi4uLi4uLi4uLi4uLkVycm9yKCVkKVxyXG4iLGFjayk7CgoKCgoKICAgICAgICAgICAgICAgIGFjaz1saWJ1c2JfY29udHJvbF90cmFuc2ZlcgoKICAgICAgICAgICAgICAgICAgICAgICAgKGlQb2RfZGV2aWNlX2hhbmRsZSwKCiAgICAgICAgICAgICAgICAgICAgICAgICBMSUJVU0JfRU5EUE9JTlRfSU58TElCVVNCX1JFQ0lQSUVOVF9ERVZJQ0UsCgogICAgICAgICAgICAgICAgICAgICAgICAgTElCVVNCX1JFUVVFU1RfR0VUX0RFU0NSSVBUT1IsCgogICAgICAgICAgICAgICAgICAgICAgICAgTElCVVNCX0RUX0NPTkZJRzw8OHwoTG9ja0NvbmZpZy0xKSwKCiAgICAgICAgICAgICAgICAgICAgICAgICAwLAoKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEsCgogICAgICAgICAgICAgICAgICAgICAgICAgNTAwLAoKICAgICAgICAgICAgICAgICAgICAgICAgIDEwMDAKCiAgICAgICAgICAgICAgICAgICAgICAgICk7CgogICAgICAgICAgICAgICAgVG90YWxJbnRlcj1kYXRhWzRdOwoKICAgICAgICAgICAgICAgIHByaW50ZigiKDYpVG90YWwgSW50ZXJmYWNlPSVkLi4uLi4uLkRvbmVcclxuIixUb3RhbEludGVyKTsKCgoKICAgICAgICAgICAgICAgIGZvcihpPTA7aTxUb3RhbEludGVyO2krKykKCiAgICAgICAgICAgICAgICB7CgogICAgICAgICAgICAgICAgICAgIGFjaz1saWJ1c2Jfa2VybmVsX2RyaXZlcl9hY3RpdmUoaVBvZF9kZXZpY2VfaGFuZGxlLGkpOwoKICAgICAgICAgICAgICAgICAgICBwcmludGYoIig2KU9TIHRva2UgSW50ZXJmYWNlJWQuLi4uLi5Eb25lKCVkKVxyXG4iLGksYWNrKTsKCiAgICAgICAgICAgICAgICAgICAgaWYoYWNrPT0xKQoKICAgICAgICAgICAgICAgICAgICB7ICAgLy/pl5zplolPU+WwjemAmWludGVyZmFjZeeahOS9v+eUqAoKICAgICAgICAgICAgICAgICAgICAgICAgZnVuY19zdGF0dXM9bGlidXNiX2RldGFjaF9rZXJuZWxfZHJpdmVyKGlQb2RfZGV2aWNlX2hhbmRsZSwgaSk7CgogICAgICAgICAgICAgICAgICAgICAgICBMb2NrSW50ZXI9aTsKCiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgIH0KCgoKICAgICAgICAgICAgLy/oqK3lrprpgJnlgItjb25maWdyYXRpb27ngrphbGl2ZQoKICAgICAgICAgICAgewoKICAgICAgICAgICAgICAgIGk9TG9ja0NvbmZpZzsKCiAgICAgICAgICAgICAgICBhY2s9bGlidXNiX3NldF9jb25maWd1cmF0aW9uKGlQb2RfZGV2aWNlX2hhbmRsZSxpKTsKCiAgICAgICAgICAgICAgICBpZihhY2s9PTApCgogICAgICAgICAgICAgICAgICAgIHByaW50ZigiKDcpU2V0IExvY2tDb25maWc9JWQuLi4uLi4uLkRvbmVcclxuIixpKTsKCiAgICAgICAgICAgICAgICBlbHNlCgogICAgICAgICAgICAgICAgICAgIHByaW50ZigiKDcpU2V0IExvY2tDb25maWcuLi4uLi4uLi4uRXJyb3IoJWQpXHJcbiIsYWNrKTsKCiAgICAgICAgICAgIH0KCgoKICAgICAgICAgICAgLy/nlLPoq4vpgJnlgIvku4vpnaLngrphbGl2ZQoKICAgICAgICAgICAgaWYoTG9ja0ludGVyIT0tMSkKCiAgICAgICAgICAgIHsKCiAgICAgICAgICAgICAgICBpPUxvY2tJbnRlcjsKCiAgICAgICAgICAgICAgICBpbnRmX3N0YXR1cz1saWJ1c2JfY2xhaW1faW50ZXJmYWNlKGlQb2RfZGV2aWNlX2hhbmRsZSxpKTsKCiAgICAgICAgICAgICAgICBpZihpbnRmX3N0YXR1cz09MCkKCiAgICAgICAgICAgICAgICAgICAgcHJpbnRmKCIoNylTZXQgTG9ja0ludGVyPSVkLi4uLi4uLi4uRG9uZVxyXG4iLGkpOwoKICAgICAgICAgICAgICAgIGVsc2UKCiAgICAgICAgICAgICAgICAgICAgcHJpbnRmKCIoNylTZXQgTG9ja0ludGVyLi4uLi4uLi4uLi5FcnJvciglZClcclxuIixhY2spOwoKICAgICAgICAgICAgfQoKCgogICAgICAgICAgICBtZW1zZXQoZGF0YSwweDAwLHNpemVvZihkYXRhKSk7CgogICAgICAgICAgICBzdHJjcHkoZGF0YSwiY2QgLy9ob21lIik7CgogICAgICAgICAgICBkYXRhWzhdPTB4RDsKCgoKICAgICAgICAgICAgYWNrPWxpYnVzYl9idWxrX3RyYW5zZmVyCgogICAgICAgICAgICAgICAgICAgIChpUG9kX2RldmljZV9oYW5kbGUsCgogICAgICAgICAgICAgICAgICAgICAyLAoKICAgICAgICAgICAgICAgICAgICAgZGF0YSwKCiAgICAgICAgICAgICAgICAgICAgIDksCgogICAgICAgICAgICAgICAgICAgICAmYWN0dWFsX2xlbmd0aAoKICAgICAgICAgICAgICAgICAgICAgLDEwMDAKCiAgICAgICAgICAgICAgICAgICAgICk7CgogICAgICAgICAgICBwcmludGYoImFjaz0lZCxkYXRhIHRhcm5zbGVuPSVkXHJcbiIsYWNrLGFjdHVhbF9sZW5ndGgpOwoKICAgICAgICB9CgogICAgICAgIGVsc2UKCiAgICAgICAgICAgIHJldHVybiAtMTsKCiAgICB9CgoKCgoKICAgIGxpYnVzYl9mcmVlX2RldmljZV9saXN0KGRldnMsIDEpOwoKCgoKCiAgICBpZihpbnRmX3N0YXR1cz09MCkKCiAgICB7CgogICAgICAgIGZ1bmNfc3RhdHVzID0gbGlidXNiX3JlbGVhc2VfaW50ZXJmYWNlKGlQb2RfZGV2aWNlX2hhbmRsZSwgaW50ZXJmYWNlKTsKCiAgICAgICAgcHJpbnRmKCJyZWxlYXNlX2ludGVyZmFjZSAlZCBzdGF0dXM9JWRcbiIsaW50ZXJmYWNlLGZ1bmNfc3RhdHVzKTsKCiAgICB9CgoKCiAgICBpZihvcGVuX3N0YXR1cz09MCkKCiAgICB7CgogICAgICAgIGxpYnVzYl9jbG9zZShpUG9kX2RldmljZV9oYW5kbGUpOwoKICAgICAgICBwcmludGYoImNsb3NlX2hhbmRsZVxuIik7CgoKCiAgICB9CgoKCiAgICBsaWJ1c2JfZXhpdChOVUxMKTsKCgoKCgp9CgoKCnZvaWQgZkdldF9kZXZpY2Vfc3RhdHVzKHN0cnVjdCBsaWJ1c2JfZGV2aWNlICpkZXYsIHN0cnVjdCBsaWJ1c2JfZGV2aWNlX2hhbmRsZSAqZGV2X2hhbmRsZSkKCnsKCiAgICBpbnQgcjsKCiAgICBzdHJ1Y3QgbGlidXNiX2RldmljZV9kZXNjcmlwdG9yIGRlc2M7CgogICAgc3RydWN0IGxpYnVzYl9jb25maWdfZGVzY3JpcHRvciAqY29uZmlnLCpjb25maWcyLCpjb25maWczOwoKICAgIGludCBpbmRleDsKCiAgICB1bnNpZ25lZCBjaGFyIGF0ZW1wc3RyaW5nWzIwMF07CgogICAgaW50IGk7CgoKCiAgICByID0gbGlidXNiX2dldF9kZXZpY2VfZGVzY3JpcHRvcihkZXYsICZkZXNjKTsKCiAgICBwcmludGYoImRldmljZV9kZXNjcmlwdG9yIHN0YXR1cz0lZFxuIixyKTsKCgoKICAgIHIgPSBsaWJ1c2JfZ2V0X2FjdGl2ZV9jb25maWdfZGVzY3JpcHRvcihkZXYsICZjb25maWcpOwoKICAgIHByaW50ZigiZ2V0X2FjdGl2ZV9jb25maWdfZGVzY3JpcHRvciBzdGF0dXM9JWRcbiIscik7CgoKCiAgICBpbmRleD0wOwoKICAgIHIgPSBsaWJ1c2JfZ2V0X2NvbmZpZ19kZXNjcmlwdG9yKGRldiwgaW5kZXgsICZjb25maWcyKTsKCiAgICBwcmludGYoImdldF9jb25maWdfZGVzY3JpcHRvciAlZCBzdGF0dXM9JWRcbiIsIGluZGV4LCByKTsKCgoKICAgIGluZGV4PTE7CgogICAgciA9IGxpYnVzYl9nZXRfY29uZmlnX2Rlc2NyaXB0b3JfYnlfdmFsdWUoZGV2LCBpbmRleCwgJmNvbmZpZzMpOwoKICAgIHByaW50ZigiZ2V0X2NvbmZpZ19kZXNjcmlwdG9yX2J5VmFsdWUgJWQgc3RhdHVzPSVkXG4iLCBpbmRleCwgcik7CgoKCiAgICBmb3IoaT0xO2k8NTtpKyspCgogICAgewoKICAgICAgICBtZW1zZXQoYXRlbXBzdHJpbmcsIDAsIDIwMCk7CgogICAgICAgIHI9bGlidXNiX2dldF9zdHJpbmdfZGVzY3JpcHRvcl9hc2NpaShkZXZfaGFuZGxlLCBpLCBhdGVtcHN0cmluZywgMjAwICk7CgogICAgICAgIHByaW50ZigiZ2V0X2NzdHJpbmdfZGVzY3JpcHRvciAlZCBfYXNjaWkgXCIlc1wiIGxlbj0lZFxuIiwgaSwgYXRlbXBzdHJpbmcsIHIpOwoKICAgIH0KCgoKICAgIGZvcihpPTE7aTw1O2krKykKCiAgICB7CgogICAgICAgIG1lbXNldChhdGVtcHN0cmluZywgMCwgMjAwKTsKCiAgICAgICAgcj1saWJ1c2JfZ2V0X2Rlc2NyaXB0b3IoZGV2X2hhbmRsZSwgTElCVVNCX0RUX0RFVklDRSwgaSwgYXRlbXBzdHJpbmcsIDIwMCApOwoKICAgICAgICBwcmludGYoImdldF9jc3RyaW5nX2Rlc2NyaXB0b3IgJWQgbGVuPSVkXG4iLCBpLCByKTsKCiAgICB9CgoKCiAgICBmb3IoaT0xO2k8NTtpKyspCgogICAgewoKICAgICAgICBtZW1zZXQoYXRlbXBzdHJpbmcsIDAsIDIwMCk7CgogICAgICAgIHI9bGlidXNiX2dldF9kZXNjcmlwdG9yKGRldl9oYW5kbGUsIExJQlVTQl9EVF9JTlRFUkZBQ0UsIGksIGF0ZW1wc3RyaW5nLCAyMDAgKTsKCiAgICAgICAgcHJpbnRmKCJnZXRfY3N0cmluZ19kZXNjcmlwdG9yICVkIGxlbj0lZFxuIiwgaSwgcik7CgogICAgfQoKCgogICAgbGlidXNiX2ZyZWVfY29uZmlnX2Rlc2NyaXB0b3IoY29uZmlnKTsKCiAgICBwcmludGYoImZyZWVfY29uZmlnX2Rlc2NyaXB0b3IiKTsKCiAgICBsaWJ1c2JfZnJlZV9jb25maWdfZGVzY3JpcHRvcihjb25maWcyKTsKCiAgICBwcmludGYoImZyZWVfY29uZmlnX2Rlc2NyaXB0b3IiKTsKCiAgICBsaWJ1c2JfZnJlZV9jb25maWdfZGVzY3JpcHRvcihjb25maWczKTsKCiAgICBwcmludGYoImZyZWVfY29uZmlnX2Rlc2NyaXB0b3IiKTsKCiAgICByZXR1cm47Cgp9CgoKCnN0cnVjdCBsaWJ1c2JfZGV2aWNlICogZmluZF9kZXZzKHN0cnVjdCBsaWJ1c2JfZGV2aWNlICoqZGV2cywgdWludDE2X3QgaXZlbmRvcikKCnsKCiAgICBzdHJ1Y3QgbGlidXNiX2RldmljZSAqZGV2OwoKICAgIHN0cnVjdCBsaWJ1c2JfZGV2aWNlX2Rlc2NyaXB0b3IgZGVzYzsKCiAgICBpbnQgaT0wLHI9MDsKCgoKICAgIHdoaWxlKChkZXY9ZGV2c1tpKytdKSE9TlVMTCkKCiAgICB7CgogICAgICAgIHI9bGlidXNiX2dldF9kZXZpY2VfZGVzY3JpcHRvcihkZXYsICZkZXNjKTsKCiAgICAgICAgaWYociA8IDApCgogICAgICAgIHsKCiAgICAgICAgICAgIGZwcmludGYoc3RkZXJyLCAiZmFpbGVkIHRvIGdldCBkZXZpY2UgZGVzY3JpcHRvciIpOwoKICAgICAgICB9CgogICAgICAgIGVsc2UKCiAgICAgICAgewoKICAgICAgICAgICAgaWYoZGVzYy5pZFZlbmRvcj09aXZlbmRvcikKCiAgICAgICAgICAgICAgICByZXR1cm4gZGV2OwoKICAgICAgICB9CgogICAgfQoKICAgIHJldHVybiAwOwoKfQoKCgp2b2lkIGxpc3RfZGV2cyhzdHJ1Y3QgbGlidXNiX2RldmljZSAqKmRldnMpCgp7CgogICAgc3RydWN0IGxpYnVzYl9kZXZpY2UgKmRldjsKCiAgICBzdHJ1Y3QgbGlidXNiX2RldmljZV9kZXNjcmlwdG9yIGRlc2M7CgogICAgaW50IGk9MCxyPTA7CgoKCiAgICB3aGlsZSgoZGV2PWRldnNbaSsrXSkhPU5VTEwpCgogICAgewoKICAgICAgICByPWxpYnVzYl9nZXRfZGV2aWNlX2Rlc2NyaXB0b3IoZGV2LCAmZGVzYyk7CgogICAgICAgIGlmKHI8MCkKCiAgICAgICAgewoKICAgICAgICAgICAgZnByaW50ZihzdGRlcnIsICJmYWlsZWQgdG8gZ2V0IGRldmljZSBkZXNjcmlwdG9yIik7CgogICAgICAgICAgICA=