[태그:] driver

  • linux usb driver xbox360(3)

    IDA 사용하기

    고유한 번호를 부여하기 위하여 define_ida, ida_simple_get, ida_simple_remove 형식으로 사용한다.

    //사용할 구조체 선언.
    struct usb_xpad{
            struct input_dev *dev;          /* input device interface */
            ...
            int pad_nr;                     // order
    };
    ...
    static DEFINE_IDA(xpad_pad_seq);
    
    
    static int xpad_led_probe(struct usb_xpad *xpad)
    {
            //ida 할당
            //pad_nr을 계속 증가..
            //led가 몇번에 연결되어 있는지 알 수 있음.
            //0~0x8,000,000 - 1까지 증가
            xpad->pad_nr = ida_simple_get(&xpad_pad_seq, 0, 0, GFP_KERNEL);
            if (xpad->pad_nr < 0){
                    retval = xpad->pad_nr;
                    goto free_mem;
            }
    
    free_mem:
            kfree(led);
            return retval;
    }

    xbox 360 패드가 4개 램프를 가지고 있다. 플레이어에 따라 램프를 달리 켜줘야 하는데, xpad->pad_nr을 ida 번호를 부여하여 4로 나눈 나머지에 2를 더했다. 5번째 패드를 붙여도 불을 것 같지만 xpad_led5이런 식으로 추가될 듯 하다. 플레이어 1과 같은 램프가 켜질 듯 하다.

    메모리가 부족하면 ida를 할당하지 못한다. xpad.c를 보면 다시 해제 하도록 했다.

    led+숫자로 등록하여 usb_unregister로 led 디바이스를 해제하면 된다. 이제 xbox 컨트롤러를 입력으로 사용하는 방법으로 넘어가도 된다.

  • linux usb driver xbox360(2)

    LED 제어하기

    xbox 360 컨트롤러가 4개 LED를 가지고 있다. 총 4명 플레이어가 있을 경우 1 ~ 4까지 시계 방향으로 램프를 켜주게 된다. usb -> input 버튼 입력을 받아 들이기 전 간단해 보는 LED 제어를 해보기로 했다. 하..어렵다. 입력 받아들이는 것 보다 더 어려운 듯 하다.

    cdev_led_register를 실행하면 /sys/class/led에 led 모듈이 등록된다.

    pi@raspberrypi:/sys/class/leds $ dmesg | tail -20
    [ 7044.723682] leds xpad_led: Setting an LED's brightness failed (-524)
    [ 7044.723824] disconnected
    [ 7344.482279] xpad is 56bd80be, xpad->udev is 7ea0c81d
    [ 7344.482296] interface is 49be3431
    [ 7344.482318] xbox360 1-1.1:1.0: interrupt in, out found. 2cedb0f6, 62b37858
    [ 7344.482579] xbox360 1-1.1:1.0: usb xbox360 driver was registerd
    [ 7344.482861] xpad is db7e959d, xpad->udev is 7ea0c81d
    [ 7344.482875] interface is c0605ae3
    [ 7344.482893] xbox360 1-1.1:1.1: interrupt in, out found. 6497d636, 4bf83f77
    [ 7344.483394] xbox360 1-1.1:1.1: usb xbox360 driver was registerd
    [ 7344.483545] usb 1-1.1: Led xpad_led renamed to xpad_led_1 due to name collision
    [ 7344.483699] xpad is 2c597e01, xpad->udev is 7ea0c81d
    [ 7344.483713] interface is dfef8df2
    [ 7344.483730] xbox360 1-1.1:1.2: Could not find both interrupt-in and interrpt-out endpoints
    [ 7344.483743] error -6
    [ 7344.483824] xpad is 2c597e01, xpad->udev is 7ea0c81d
    [ 7344.483837] interface is f1417f63
    [ 7344.483852] xbox360 1-1.1:1.3: Could not find both interrupt-in and interrpt-out endpoints
    [ 7344.483865] error -6
    [ 7344.483985] usbcore: registered new interface driver xbox360
    
    
    pi@raspberrypi:/sys/class/leds $ ls -tl
    total 0
    lrwxrwxrwx 1 root root 0 Jan  4 23:52 xpad_led -> ../../devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.1/leds/xpad_led
    lrwxrwxrwx 1 root root 0 Jan  4 23:52 xpad_led_1 -> ../../devices/platform/scb/fd500000.pcie/pci0000

    xbox 컨트롤러가 총 4개를 등록할 수 있는데, 인터럽트로 2개를 등록할 수 있다. 나머지 2개는 무엇인지 모르겠다. 암튼 xpad.c는 2번만 등록했다.

    CDEV_LED로 등록을 하면 brightness_set 함수를 overload 할 수 있다. brightness_set -> xpad_led_set -> xpad_send_led_command으로 연결한다. xpad_send_led_command 안에서 LED 제어하는 패킷을 만들어 URB에 넣어 준다. urb->transfer_buffer_length를 잘 넣어줘야 URB 패킷을 전송한다.

    인터럽트로 한번 등록하면 일정 주기로 계속 명령을 실행한다.

    [  340.057841] xpad is c97d9e68, xpad->udev is decb56d0
    [  340.057858] interface is d89e5572
    [  340.057871] cur_altsetting is 2
    [  340.057893] xbox360 1-1.1:1.0: interrupt in, out found. 00000000, 3b46194c
    [  340.058231] xbox360 1-1.1:1.0: usb xbox360 driver was registerd
    [  340.058253] dma output address 6ce62de4 with size 64, point to f2c4e403 was allocated
    [  340.058266] actual address is 6ce62de4
    [  340.058280] urb was allocated
    [  340.058292] xpad->endpoint_out->bInterval is 8
    [  340.058306] XPAD_OUT_LED_IDX: 2
    [  340.058318] XPAD_NUM_OUT_PACKETS: 3
    [  340.058440] xpad->led_command->data[0]:1,[1]:3,[2]:10, with 3 len
    [  340.058463] xpad_send_led_command: completed
    [  340.058828] usbcore: registered new interface driver xbox360
    [  359.127170] usbcore: deregistering interface driver xbox360
    [  359.127225] xpad address is c97d9e68, intf is d89e5572
    [  359.129187] xpad->led_command->data[0]:1,[1]:3,[2]:0, with 3 len
    [  359.129217] xbox360 1-1.1:1.0: xpad_send_led_command - usb_submit_urb failed with -ENOENT
    [  359.131553] xpad led was unregistered
    [  359.131575] dma output address 6ce62de4 with size 64 was freed
    [  359.131590] disconnected

    10번을 보내면 LED가 rotate 한다.

    –추가–

    • interrupt 등록, usb_submit_urb 완료 함수(xpad_irq_outfn) 등록.
    • set_brightness로 led 밝기 조정 함수에 등록.
    • xpad->urb_active == true일 경우 명령에 맞는 패킷 만들어 전송.
    • xpad_irq_outfn 안ㅔ서 xpad->urb_active = false로 수정. xpad->urb_active가 없으면 일정 주기로 계속 실행됨.

    참조 사이트.

  • linux usb driver xbox360(1)

    집에서 놀고 있던 8년 전에 구매한 xbox 360 유선 usb 패드를 raspberry pi4에 등록하여 사용하고 싶다. 나온 지 오래되어 이미 xpad 리눅스 드라이버가 공개되어 있다. 그러나 usb, input을 한번에 사용하여 잘 이해되지 않는다. 남은 출장 기간 중 천천히 공부 하기로 했다.

    usb를 등록하려면 vendor id, product id, 연결되면 실행되는 call back probe, disconnect 등 을 알아야 한다. 인터넷에 공개된 좋은 자료, 소스를 공부했다. 관련 코드는 여기에 저장했다.

    usb-devices로 xbox 패드를 확인하면 (I가 interface 인듯하다) 0, 1, 2, 3인터페이스가 등록되지 않았다.

    pi@raspberrypi:~/rasp/xbox_driver $ usb-devices 
    T:  Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=12  MxCh= 0
    D:  Ver= 2.00 Cls=ff(vend.) Sub=ff Prot=ff MxPS= 8 #Cfgs=  1
    P:  Vendor=045e ProdID=028e Rev=01.14
    S:  Manufacturer=©Microsoft Corporation
    S:  Product=Controller
    S:  SerialNumber=0C59FC4
    C:  #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=500mA
    I:  If#=0x0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=5d Prot=01 Driver=(none)
    I:  If#=0x1 Alt= 0 #EPs= 4 Cls=ff(vend.) Sub=5d Prot=03 Driver=(none)
    I:  If#=0x2 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=5d Prot=02 Driver=(none)
    I:  If#=0x3 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=fd Prot=13 Driver=(none)

    usb_register_dev로 interface 0, 1을 등록했다.

    pi@raspberrypi:~/rasp/xbox_driver $ usb-devices 
    T:  Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=12  MxCh= 0
    D:  Ver= 2.00 Cls=ff(vend.) Sub=ff Prot=ff MxPS= 8 #Cfgs=  1
    P:  Vendor=045e ProdID=028e Rev=01.14
    S:  Manufacturer=©Microsoft Corporation
    S:  Product=Controller
    S:  SerialNumber=0C59FC4
    C:  #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=500mA
    I:  If#=0x0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=5d Prot=01 Driver=xbox360
    I:  If#=0x1 Alt= 0 #EPs= 4 Cls=ff(vend.) Sub=5d Prot=03 Driver=xbox360
    I:  If#=0x2 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=5d Prot=02 Driver=(none)
    I:  If#=0x3 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=fd Prot=13 Driver=(none)
    
    pi@raspberrypi:~/rasp/xbox_driver $ dmesg 
    [48226.848081] xpad is 0c15d4e5, xpad->udev is 14758ec9
    [48226.848101] interface is 913f883f
    [48226.848126] xbox360 1-1.1:1.0: interrupt in, out found. 55429370, 0119bb5d
    [48226.848528] xbox360 1-1.1:1.0: usb xbox360 driver was registerd
    [48226.848710] xpad is a5c87389, xpad->udev is 14758ec9
    [48226.848726] interface is f687e098
    [48226.848746] xbox360 1-1.1:1.1: interrupt in, out found. efcdcd2e, 2fcb2b2f
    [48226.849000] xbox360 1-1.1:1.1: usb xbox360 driver was registerd
    [48226.849162] xpad is 5c5394a1, xpad->udev is 14758ec9
    [48226.849178] interface is 7fa06804
    [48226.849196] xbox360 1-1.1:1.2: Could not find both interrupt-in and interrpt-out endpoints
    [48226.849211] error -6
    [48226.849304] xpad is 5c5394a1, xpad->udev is 14758ec9
    [48226.849320] interface is c9ea30ca
    [48226.849337] xbox360 1-1.1:1.3: Could not find both interrupt-in and interrpt-out endpoints
    [48226.849352] error -6
    [48226.849490] usbcore: registered new interface driver xbox360

    참조 사이트.

  • Essential Linux Device Drivers

    Essential Linux Device Drivers

    isbn: 9788960771499

    한글판 제목이 너무 길어 원서 제목을 썼다. 임베디드 개발자면 쉽게 이해하겠지만 배경 지식이 없는 나에게는 너무 어렵다. 그럼에도 기록을 남겨, 나중에 어떤 책이 좋은지 다시 판단하는 시간을 줄이고, 다시 보려 한다.

    책 내용에 코드가 많은데 독자가 실행시킬 수 없어 어떻게 돌아가는지 알 수 없다. 커널을 설명한 부분도 있는데, 이미 알고 있다면 안 읽어도 될 듯 하다.

    작가 꿈이 큰지 usb, i2c, 캐릭터 디바이스, 심지어 그래픽 드라이버까지 설명했다. 나같이 취미로 생각하는 사람이 이런 기술을 알 필요는 없다. 5~10년 사이에 사라질 수 도 있다. 다 읽기는 어렵고, 지루하고, 쓸모없어 대략 다음 장 개념 정도만 보면 될 듯 하다. 코드는 최신 리눅스 커널을 보는게 맞다.

    • 문자 드라이버
    • 직력 드라이버
    • 입력 드라이버
    • usb
    • 네트웍 인터페이스 카드

    Linux Device Drivers(isbn: 9780596005900)를 읽고 난 후 다시 봐야겠다. 이 분야 원탑 이라는데 인터넷에서 무료로 구할 수 있다. 절판이고 하고.

  • xbox 360 드라이버 만지기1

    xbox 360 드라이버 만지기1

    내 라즈베리 파이에 usb 타입 xbox360 패드를 붙여 보고싶다. 리눅스 커널 xpad.c에 마이크로소프트 거의 모든 제품 usb vendor, product id가 등록되어 있다. xpad.c가 조금 복작하여 usb 인터럽트 사용 방법을 잘 이해할 수 없다. 키 입력 설정을 어떻게 할지는 나중 문제고… usb-skeletion.c 문서 역시 어렵다. 여기는 인터럽트 대신 대용량 데이터 전송을 목표로 했다.

    그 중 가장 비슷한 usb 마우스 드라이버를 커널에서 찾았다. 커널이 성경과 같아 모든 물음에 대한 답을 한다. 200줄 약간 넘어가는 코드로 정말 인터럽트 핵심만 작성했다.

    대략 구성은 아래와 같이 된다.

    • usb 구조체 선언.
    • 사용가능한 usb 번호 찾음, 등록.
    • 입력 설정.
    • 인터럽트 설정.

    usb_fill_int_urb로 call 함수를 등록하여 인터럽트를 사용하면 된다. usb 인터럽트가 일정 주기로 발생한다. 계속 실행하기 위해 인터럽트로 실행할 함수 안에 usb_submit_urb를 넣는다. 알고보면 참 쉬운데 처음 이해하기 어렵다. xpad.c도 같은 방식이다. 처음에 왜 안보였는지…아직 키 입력을 설정하지 않았고, 커널에 test를 출력하도록 했다.

    usb 구조체는 여러 정보를 쉽게 사용하려 군더더기를 많이 붙이는 듯 하다.

    #include <linux/kernel.h>
    #include <linux/input.h>
    #include <linux/module.h>
    #include <linux/usb/input.h>
    #include <linux/init.h>
    #include <linux/device.h>
    #include <linux/usb/input.h>
    #include <linux/slab.h>
    #define USB_XBOX_MINOR_BASE	1
    		
    //구조체 선언.
    struct usb_xpad{
    	struct input_dev *dev;		/* input device interface */
    	struct usb_device *udev;	/* usb device */
    	struct usb_interface *intf;	/* usb interface */
    	__u8    irq_in_endpointAddr;    /* interrupt in address*/
    	__u8    irq_out_endpointAddr;   /* interrupt out address*/
    	struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
    	signed char *data;		/* input data */
    	struct urb *irq_in;		/* urb for interrupt in report*/
    	struct work_struct work;	/* init/remove device from callback */
    };
    static struct usb_xpad *myPad;
    static int xpad_init_input(struct usb_xpad *xpad);
    static void xpad_deinit_input(struct usb_xpad *xpad);
    static void usb_xpad_irq(struct urb *urb){
    	pr_info("test\n");
    	usb_submit_urb(urb, GFP_KERNEL);
    }
    static int xpad_init_urb(struct usb_interface *intf, struct usb_xpad *xpad);
    static ssize_t xbox_read(struct file *file, char *buffer, size_t count,
    			 loff_t *ppos)
    {
    	pr_info("device was read.\n");
    	return 0;
    }
    static ssize_t xbox_write(struct file *file, const char *user_buffer,
    			  size_t count, loff_t *ppos)
    {
    	return 0;
    }
    static int xbox_open(struct inode *inode, struct file *file)
    {
    	int retval;
    	struct urb *ptr_urb;
    	ptr_urb = usb_alloc_urb(0, GFP_KERNEL);
    	pr_info("device was opened.\n");
    	if (!ptr_urb) {
    		retval = -ENOMEM;
    		goto error;
    	}
    	return 0;
    error:
    	if(ptr_urb)
    	{
    		usb_free_urb(ptr_urb);
    	}
    	return retval;
    }
    static int xbox_release(struct inode *inode, struct file *file)
    {
    	pr_info("xbox was released\n");
    	return 0;
    }
    static int xbox_flush(struct file *file, fl_owner_t id)
    {
    	return 0;
    }
    static const struct file_operations xboxtest_fops = {
    	.owner =	THIS_MODULE,
    	.read =		xbox_read,
    	.write =	xbox_write,
    	.open =		xbox_open,
    	.release =	xbox_release,
    	.flush =	xbox_flush,
    	.llseek =	noop_llseek,
    };
    /*
     * usb class driver info in order to get a minor number from the usb core,
     * and to have the device registered with the driver core
     */
    static struct usb_class_driver xbox_class = {
    	.name =		"xbox%d",
    	.fops =		&xboxtest_fops,
    	.minor_base =	USB_XBOX_MINOR_BASE,
    };
    static struct usb_driver xpad_test_driver;
    static const struct usb_device_id xpad_table[] = {
    	//{ USB_INTERFACE_INFO('X', 'B', 0) },	/* X-Box USB-IF not approved class */
    	//XPAD_XBOX360_VENDOR(0x045e),		/* Microsoft X-Box 360 controllers */
    	{USB_DEVICE(0x045e, 0x028e)},
    	{ }
    };
    static const signed short xpad_common_btn[] = {
    	BTN_A, BTN_B, BTN_X, BTN_Y,			/* "analog" buttons */
    	BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR,	/* start/back/sticks */
    	-1						/* terminating entry */
    };
    MODULE_DEVICE_TABLE(usb, xpad_table);
    static int xpad_init_input(struct usb_xpad *xpad)
    {
    	struct input_dev *input_dev;
    	int i, error;
    	int pipe, maxp;
    	input_dev = input_allocate_device();
    	if (!input_dev)
    		return -ENOMEM;
    	xpad->dev = input_dev;
    	usb_to_input_id(xpad->udev, &input_dev->id);
    	input_set_drvdata(input_dev, xpad);
    	/* set up standard buttons */
    	for (i = 0; xpad_common_btn[i] >= 0; i++)
    		input_set_capability(input_dev, EV_KEY, xpad_common_btn[i]);
    	pipe = usb_rcvintpipe(xpad->udev, xpad->irq_in_endpointAddr);
    	maxp = usb_maxpacket(xpad->udev, pipe, usb_pipeout(pipe));
    	usb_fill_int_urb(xpad->irq_in, xpad->udev,
    			pipe, xpad->data,
    			(maxp > 8 ? 8 : maxp),
    			usb_xpad_irq, xpad, 
    			xpad->endpoint_in->bInterval);
    	error = input_register_device(input_dev);
    	if (error)
    		goto err_free_dev;
    	pr_info("usb input was registered\n");
    	usb_submit_urb(xpad->irq_in, GFP_KERNEL);
    	return 0;	//return ok;
    err_free_dev:
    	input_free_device(input_dev);
    	return error;
    }
    static void xpad_deinit_input(struct usb_xpad *xpad)
    {
    	pr_info("xpad is %p, ->dev is %p.\n",xpad, xpad->dev);
    	if(xpad->dev)
    		input_unregister_device(xpad->dev);
    }
    static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
    {
    	struct usb_xpad *xpad;
    	struct usb_device *udev;
    	struct usb_endpoint_descriptor *ep_irq_in,*ep_irq_out;
    	struct usb_host_interface *intf_tmp;
    	int retval;
    	udev = interface_to_usbdev(intf);
    	xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
    	if (!xpad)
    		return -ENOMEM;
    	//초기화
    	//kzallocd으로 0으로 초기화
    	//xpad->odata_serial = 0;
    	xpad->udev = udev;
    	xpad->intf = intf;
    	myPad = xpad;
    	pr_info("xpad is %p, myPad is %p\n", xpad->intf, myPad->intf);
    	pr_info("interface is %p\n", intf);
    	//if (intf->cur_altsetting->desc.bNumEndpoints != 2)
    	//	return -ENODEV;
    	intf_tmp = intf->cur_altsetting;
    	// find common usb endpoint helper 사용
    	//https://lkml.org/lkml/2020/9/21/1239
    	
    	/* set up the endpoint information */
    	/* use only the first bulk-in and bulk-out endpoints */
    	retval = usb_find_common_endpoints(intf_tmp,
    			NULL, NULL, &ep_irq_in, &ep_irq_out);
    	if (retval) {
    		dev_err(&intf->dev,
    			"Could not find both irq-in and irq-out endpoints\n");
    		goto error;
    	}
    	xpad->irq_in_endpointAddr = ep_irq_in->bEndpointAddress;
    	xpad->irq_out_endpointAddr = ep_irq_out->bEndpointAddress;
    	xpad->endpoint_in = ep_irq_in;
    	xpad->endpoint_out = ep_irq_out;
    	xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL);
    	if (!xpad->irq_in) {
    		retval = -ENOMEM;
    		goto err_free_in_urb;
    	}
    	usb_set_intfdata(intf, xpad);
    	pr_info("[info]: found interrupt end point, in: %d, out: %d", ep_irq_in->bEndpointAddress, ep_irq_out->bEndpointAddress);
    	pr_info("probe \n");
    	//pr_info("%04X:%04X pluged \n", id->idVendor, id->idProduct);
    	retval = usb_register_dev(intf, &xbox_class);
    	if (retval< 0) {
    		pr_err("usb_register failed for the "__FILE__ "driver."
    				"Error number %d", retval);
    		usb_set_intfdata(intf, NULL);
    		goto error;
    	}
    	/* let the user know what node this device is now attached to */
    	dev_info(&intf->dev,
    		 "USB Skeleton device now attached to USBSkel-%d",
    		 intf->minor);
    	//input으로 등록.
    	xpad_init_input(xpad);
    	
    	return 0;
    error:
    	kfree(xpad);
    	return retval;
    err_free_in_urb:
    	usb_free_urb(xpad->irq_in);
    	return retval;
    }
    static void xpad_disconnect(struct usb_interface *intf)
    {
    	struct usb_xpad *xpad;
    	xpad = usb_get_intfdata(intf);
    	pr_info("xpad address is %p\n", xpad);
    	xpad_deinit_input(xpad);
    	usb_deregister_dev(intf, &xbox_class);
    	usb_set_intfdata(intf, NULL);
    	kfree(xpad);
    	pr_info("disconnected\n");
    }
    static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
    {
    	pr_info("suspendes\n");
    	return 0;
    }
    static int xpad_resume(struct usb_interface *intf)
    {
    	pr_info("resumed\n");
    	return 0;
    }
    static struct usb_driver xpad_test_driver = {
    	.name		= "xbox360_test",
    	.probe		= xpad_probe,
    	.disconnect	= xpad_disconnect,
    	.suspend	= xpad_suspend,
    	.resume		= xpad_resume,
    	.id_table	= xpad_table,
    };
    static int xpad_init_urb(struct usb_interface *intf, struct usb_xpad *xpad)
    {
    	int retval;
    	xpad->irq_in= usb_alloc_urb(0, GFP_KERNEL);
    	if (!xpad->irq_in) {
    		retval = -ENOMEM;
    		goto error;
    	}
    	return 0;
    error:
    	return retval;
    }
    	
    // 모듈 loading, unloading 테스트를 위해 과거 방식으로 사용
    //module_init(usb_xboxtest_init);
    //module_exit(usb_xboxtest_exit);
    //Macro
    module_usb_driver(xpad_test_driver);
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("now0930");
    MODULE_DESCRIPTION("Hello, xbox pad!");
    
    [45180.903315] xpad is ea6ce566, myPad is ea6ce566
    [45180.903332] interface is ea6ce566
    [45180.903349] [info]: found interrupt end point, in: 129, out: 1
    [45180.903360] probe 
    [45180.903636] xbox360_test 1-1.2:1.0: USB Skeleton device now attached to USBSkel-1
    [45180.903815] input: Unspecified device as /devices/virtual/input/input8
    [45180.904290] usb input was registered
    [45180.904475] xpad is 50c63d58, myPad is 50c63d58
    [45180.904489] interface is 50c63d58
    [45180.904506] [info]: found interrupt end point, in: 130, out: 2
    [45180.904518] probe 
    [45180.904685] xbox360_test 1-1.2:1.1: USB Skeleton device now attached to USBSkel-2
    [45180.904841] input: Unspecified device as /devices/virtual/input/input9
    [45180.905155] usb input was registered
    [45180.905310] xpad is 3bfd76ed, myPad is 3bfd76ed
    [45180.905323] interface is 3bfd76ed
    [45180.905342] xbox360_test 1-1.2:1.2: Could not find both irq-in and irq-out endpoints
    [45180.905432] xpad is 07d8d175, myPad is 07d8d175
    [45180.905451] interface is 07d8d175
    [45180.905469] xbox360_test 1-1.2:1.3: Could not find both irq-in and irq-out endpoints
    [45180.905585] usbcore: registered new interface driver xbox360_test
    [45180.909177] test
    [45180.913170] test
    [45210.971462] test
    [45210.984592] test
    [45210.997466] test
    [45211.010595] test
    [45211.075485] test
    [45211.088606] test
    [45211.109483] test
    [45211.130612] test
    [45211.151488] test
    [45211.168617] test
    [45211.181493] test
    [45211.754713] test
    [45211.799598] test
    [45211.812711] test
    [45212.329679] test
    [45217.545918] usbcore: deregistering interface driver xbox360_test
    [45217.546248] test
    [45217.546378] xpad address is 99d70f22
    [45217.546411] xpad is 99d70f22, ->dev is 8784f33d.
    [45217.699130] disconnected
    [45217.699578] test
    [45217.699674] xpad address is 0764c1af
    [45217.699692] xpad is 0764c1af, ->dev is 379dff77.
    [45217.779137] disconnected