Linux USB Gadget - 각 부분의 통합

Linux USB Gadget 소프트웨어 구 조 는 한 글 에서 Linux USB Gadget 소프트웨어 를 3 층 으로 나 누 었 다.이 3 층 중 2 층 은 하드웨어 와 무관 하 며 각각 Gadget 기능 구동 층, USB 장치 층 이다.1 층 은 하드웨어 와 관련 된 UDC 층 이다.모든 층 은 관건 적 인 데이터 구조 와 함수 와 다른 층 의 상호작용 을 제공한다.
        Gadget 기능 구동 층: 가장 주요 한 구 조 는 struct usbcomposite_driver, 이 구 조 는 이 층 에서 정의 되 고 구조 중의 각 함 수 를 실현 합 니 다.
        USB 장치 계층: 가장 주요 한 데이터 구 조 는 struct usbcomposite_dev 와 usbgadget_driver。이전 하 나 는 USB 장 치 를 대표 하고, 다음 하 나 는 Gadget 구동 으로 UDC 층 과 상호작용 을 한다.
        UDC 층: 가장 주요 한 데이터 구 조 는 struct usbgadget, 보통 다른 구조 체 에 포함 되 어 있 습 니 다.이 구조 체 는 USB 장치 컨트롤 러 의 모든 USB 통신 에 관 한 정 보 를 대표 한다.
        UDC 층 제공 usbgadget_unregister_driver (struct usb gadget driver * driver) 함수, 이 함 수 는 USB 장치 층 에서 호출 되 며, USB 장치 층 은 자신 이 정의 하 는 struct usbgadget_driver 구조 변 수 를 그 에 게 전달 합 니 다.USB 장치 층 제공 usbcomposite_register (struct usb composite driver * driver) 함수, 이 함 수 는 Gadget 기능 구동 층 에서 호출 되 며, Gadget 기능 구동 층 은 자신 이 정의 하 는 struct usbcomposite_driver 구조 변 수 를 그 에 게 전달 합 니 다.이 3 층 이 어떻게 결합 되 었 는 지 상세 하 게 분석 해 보 자.저 희 는 zero Gadget 기능 구동 을 예 로 들 어 s3c 2410udc 는 밑바닥 UDC 로
        먼저 zero Gadget 기능 구동 을 살 펴 보 겠 습 니 다. 그 는 하나의 모듈 로 커 널 에 등록 되 었 습 니 다. 먼저 그의 모듈 초기 화 함 수 를 분석 하 겠 습 니 다.
static int __init init(void)
{
	return usb_composite_register(&zero_driver);
}
        아주 간단 합 니 다. usb 만 호출 했 습 니 다.composite_register, 그 에 게 전 달 된 매개 변 수 는 zerodriver。이 구조 체 는 다음 과 같이 정의 합 니 다.
static struct usb_composite_driver zero_driver = {
	.name		= "zero",
	.dev		= &device_desc,
	.strings	= dev_strings,
	.bind		= zero_bind,
	.unbind		= zero_unbind,
	.suspend	= zero_suspend,
	.resume		= zero_resume,
};
        이상 의 함 수 는 모두 zero. c 에서 이 루어 집 니 다. 비교적 중요 한 함 수 는 zero 입 니 다.bind。현재 이 함 수 를 잠시 열거 하지 않 고 사용 할 때 다시 이야기 합 시다.다음은 usbcomposite_register 함수, 그 는 USB 장치 층 에서 제공 한 것 으로 coposite. c 에서 정의 합 니 다.
int __init usb_composite_register(struct usb_composite_driver *driver)
{
	if (!driver || !driver->dev || !driver->bind || composite)
		return -EINVAL;

	if (!driver->name)
		driver->name = "composite";
	composite_driver.function =  (char *) driver->name;
	composite_driver.driver.name = driver->name;
	composite = driver;

	return usb_gadget_register_driver(&composite_driver);
}
        이 함수 의 주요 목적 은 두 개의 구조 체 변 수 를 초기 화 하 는 것 입 니 다. 하 나 는 coposite 입 니 다.driver, 이것 은 USB 장치 층 이 정의 하 는 전역 struct usbgadget_driver 변 수 는 다음 과 같 습 니 다.
static struct usb_gadget_driver composite_driver = {
	.speed		= USB_SPEED_HIGH,

	.bind		= composite_bind,
	.unbind		= __exit_p(composite_unbind),

	.setup		= composite_setup,
	.disconnect	= composite_disconnect,

	.suspend	= composite_suspend,
	.resume		= composite_resume,

	.driver	= {
		.owner		= THIS_MODULE,
	},
};
        이 함수 들 은 모두 USB 장치 층 에서 이 루어 져 야 한다.usb_composite_register 는 compositedriver 의 function 이 "zero" 로 초기 화 되 었 습 니 다.driver 는 struct devicedriver 구조 체.링크 ux 장치 모델 에서 사용 합 니 다.이름 이 "zero" 로 초기 화 되 었 습 니 다.또 다른 변 수 는 coposite 입 니 다. USB 장치 층 이 정의 하 는 struct usb 입 니 다.composite_driver 의 지침, 이렇게 coposite 는 zero 를 가리 키 고 있 습 니 다.driver。그래서 제로 가 젯 기능 구동 층 은 USB 장치 층 과 연결 되 어 있다.마지막 usbcomposite_register 함수 호출 usbgadget_register_driver, UDC 층 에 연락 하기 시작 합 니 다.이 함 수 는 UDC 층 에 정의 되 어 있 으 며, 시스템 의 모든 UDC 는 이러한 함 수 를 실현 해 야 한다.s3c 2410udc 이 함수 의 실현:
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
	struct s3c2410_udc *udc = the_controller; //the_controller          s3c2410_udc  ,       s3c2410 usb     ,     struct gadget  
	int		retval;

	dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'
", driver->driver.name); /* Sanity checks */ if (!udc) return -ENODEV; if (udc->driver) return -EBUSY; if (!driver->bind || !driver->setup || driver->speed < USB_SPEED_FULL) { printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d
", driver->bind, driver->setup, driver->speed); return -EINVAL; } #if defined(MODULE) if (!driver->unbind) { printk(KERN_ERR "Invalid driver: no unbind method
"); return -EINVAL; } #endif /*--------------------------------------- -------------------------------------------------------*/ /* Hook the driver */ udc->driver = driver;// driver USB composite_driver, UDC USB udc->gadget.dev.driver = &driver->driver; // driver struct device_driver , linux /* Bind the driver */ if ((retval = device_add(&udc->gadget.dev)) != 0) { printk(KERN_ERR "Error in device_add() : %d
",retval); goto register_error; } //udc->gadget.dev struct device , linux dprintk(DEBUG_NORMAL, "binding gadget driver '%s'
", driver->driver.name); if ((retval = driver->bind (&udc->gadget)) != 0) { device_del(&udc->gadget.dev); goto register_error; } /* Enable udc */ s3c2410_udc_enable(udc); return 0; register_error: udc->driver = NULL; udc->gadget.dev.driver = NULL; return retval; }
    이 함수 의 첫 번 째 기능 은 UDC 층 을 USB 장치 층 과 연결 한 다음 driver - > bid (& udc - > gadget) 함 수 를 호출 하 는 것 입 니 다.가장 중요 한 귀속 작업 을 시작 했다.이 함수 가 실행 되 어야 이 3 층 이 진정 으로 결합 되 고 USB 장치 가 정상적으로 작 동 합 니 다.driver 는 USB 장치 층 에서 정 의 된 coposite 를 전달 합 니 다.driver。그래서 driver - > bid (& udc - > gadget) 함 수 는 coposite. c 에서 정 의 된 것 입 니 다. 다음 과 같 습 니 다.
static int __init composite_bind(struct usb_gadget *gadget)
{
	struct usb_composite_dev	*cdev;
	int				status = -ENOMEM;

	cdev = kzalloc(sizeof *cdev, GFP_KERNEL);  //    ,struct usb_composite_dev       USB  
	if (!cdev)
		return status;

	spin_lock_init(&cdev->lock);
	cdev->gadget = gadget;   //  gadget   s3c2410_udc.c    
	set_gadget_data(gadget, cdev); //           gadget->dev->driver_data  cdev  。gadget->dev struct device        Linux        
	INIT_LIST_HEAD(&cdev->configs);  //cdev->configs struct list_head    ,              

	/* preallocate control response and buffer */
	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
        //              ,   USB    。      ,    USB                
	if (!cdev->req)
		goto fail;
	cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
	if (!cdev->req->buf)
		goto fail;
	cdev->req->complete = composite_setup_complete;
	gadget->ep0->driver_data = cdev;

	cdev->bufsiz = USB_BUFSIZ;
	cdev->driver = composite; //  struct usb_composite_dev    USB  ,       Gadget    ,   composite,   usb_composite_register     zero_driver

	usb_gadget_set_selfpowered(gadget); //  USB        ,     mini2440         ,       

	/* interface and string IDs start at zero via kzalloc.
	 * we force endpoints to start unassigned; few controller
	 * drivers will zero ep->driver_data.
	 */
	usb_ep_autoconfig_reset(cdev->gadget);//            gadget    ,    driver_data  

	/* composite gadget needs to assign strings for whole device (like
	 * serial number), register function drivers, potentially update
	 * power state and consumption, etc
	 */
	status = composite->bind(cdev); //          Gadget      ,     zero.c,composite->bind   zero.c 。                  。
	if (status < 0)
		goto fail;
        //              ,cdev->desc truct usb_device_descriptor       USB     。   Gadget                   
	cdev->desc = *composite->dev;
	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

	/* standardized runtime overrides for device ID data */
	if (idVendor)
		cdev->desc.idVendor = cpu_to_le16(idVendor);
	if (idProduct)
		cdev->desc.idProduct = cpu_to_le16(idProduct);
	if (bcdDevice)
		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);

	/* strings can't be assigned before bind() allocates the
	 * releavnt identifiers
	 */
	if (cdev->desc.iManufacturer && iManufacturer)
		string_override(composite->strings,
			cdev->desc.iManufacturer, iManufacturer);
	if (cdev->desc.iProduct && iProduct)
		string_override(composite->strings,
			cdev->desc.iProduct, iProduct);
	if (cdev->desc.iSerialNumber && iSerialNumber)
		string_override(composite->strings,
			cdev->desc.iSerialNumber, iSerialNumber);

	INFO(cdev, "%s ready
", composite->name); return 0; fail: composite_unbind(gadget); return status; }
        composite_bind 는 먼저 struct usb 를 정의 하고 초기 화 했 습 니 다.composite_dev 구조 체, cdev - > gadget = gadget 을 통 해;이 문 구 는 장 치 를 바 텀 gadget 과 연결 시 키 고 cdev - > driver = coposite 를 통 해 장치 와 Gadget 기능 구동 을 연결 합 니 다.그리고 장치 터미널 0 에 struct usb 를 할당 하 였 습 니 다.request, 이 구 조 는 USB 매 거 진 에서 중요 한 역할 을 발휘 할 것 이다.그리고 Gadget 기능 구동 층 의 bind 함 수 를 호출 합 니 다.마지막 으로 USB 장치 설명 자 를 초기 화 했 습 니 다.이 함수 의 가장 중요 한 단 계 는 Gadget 기능 구동 층 의 bind 함 수 를 호출 하 는 것 이다.이렇게 해서 야 세 개의 소프트웨어 층 이 진정 으로 연결 되 었 다.zero Gadget 기능 구동 층 의 bind 함 수 는 zero. c 에서 다음 과 같이 정의 합 니 다.
static int __init zero_bind(struct usb_composite_dev *cdev)
{
	int			gcnum;
	struct usb_gadget	*gadget = cdev->gadget;
	int			id;

	/* Allocate string descriptor numbers ... note that string
	 * contents can be overridden by the composite_dev glue.
	 */
	id = usb_string_id(cdev); 
//          cdev->next_string_id   254, cdev->next_string_id 1,   1  cdev->next_string_id。  cdev->next_string_id 0。         id = 1;
	if (id < 0)
		return id;
	strings_dev[STRING_MANUFACTURER_IDX].id = id;
	device_desc.iManufacturer = id;
//strings_dev zero           ,                     id 1
	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_PRODUCT_IDX].id = id;
	device_desc.iProduct = id;
//                   id 2
	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_SERIAL_IDX].id = id;
	device_desc.iSerialNumber = id;
//                     id 3
	setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
//        ,     
	/* Register primary, then secondary configuration.  Note that
	 * SH3 only allows one config...
	 */
	if (loopdefault) {
		loopback_add(cdev, autoresume != 0);
		if (!gadget_is_sh(gadget))
			sourcesink_add(cdev, autoresume != 0);
	} else {
		sourcesink_add(cdev, autoresume != 0);
		if (!gadget_is_sh(gadget))
			loopback_add(cdev, autoresume != 0);
	}
//        ,   zero        。        zero     ,      。                  ,                 。loopdefault     ,    0
//      else     ,                 。gadget_is_sh   usb             ,s3c2410   。         sourcesink_add(cdev, autoresume != 0)
//        ,   sourcesink_add(cdev, autoresume != 0)    。
	gcnum = usb_gadget_controller_number(gadget);
	if (gcnum >= 0)
		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
	else {
		/* gadget zero is so simple (for now, no altsettings) that
		 * it SHOULD NOT have problems with bulk-capable hardware.
		 * so just warn about unrcognized controllers -- don't panic.
		 *
		 * things like configuration and altsetting numbering
		 * can need hardware-specific attention though.
		 */
		pr_warning("%s: controller '%s' not recognized
", longname, gadget->name); device_desc.bcdDevice = cpu_to_le16(0x9999); } INFO(cdev, "%s, version: " DRIVER_VERSION "
", longname); snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); return 0; }
        zero_bid 함 수 는 먼저 문자열 설명자 의 id 를 설정 한 다음 USB 설정 을 설정 합 니 다.주로 sourcesink 호출add 함수, 전달 하 는 매개 변 수 는 cdev 이 고 USB 장치 층 이 정의 하 는 USB 장치 구조 체 입 니 다.이 함수 정의 fsourcesink. c, 이 파일 은 헤더 파일 형식 으로 zero. c 에 포함 되 어 있 습 니 다.다음 과 같다.
int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)
{
	int id;

	/* allocate string ID(s) */
	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_sourcesink[0].id = id;
        //              id
	source_sink_intf.iInterface = id;
	sourcesink_driver.iConfiguration = id;
        //source_sink_intf struct usb_interface_descriptor     ,      
        //sourcesink_driver struct usb_configuration     ,    USB  ,         。      f_sourcesink.c   
	/* support autoresume for remote wakeup testing */
	if (autoresume)
		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;

	/* support OTG systems */
	if (gadget_is_otg(cdev->gadget)) {
		sourcesink_driver.descriptors = otg_desc;
		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	return usb_add_config(cdev, &sourcesink_driver);
}
                   f_sourcesink.c          ,sourcesink_driver。      USB  ,          。  :
static struct usb_configuration sourcesink_driver = {
	.label		= "source/sink",
	.strings	= sourcesink_strings,
	.bind		= sourcesink_bind_config,
	.setup		= sourcesink_setup,
	.bConfigurationValue = 3,
	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
	/* .iConfiguration = DYNAMIC */
};
        이 데이터 구 조 를 보고 sourcesink 분석 해 보 겠 습 니 다.add 마지막 호출 함수 usbadd_config (cdev, & sourcesink driver), 이 함수 가 전달 하 는 매개 변 수 는 USB 장치 이 고 하 나 는 USB 설정 입 니 다.분명히 기능 은 USB 장치 에 설정 을 추가 하 는 것 이다.함수 정 의 는 coposite. c 에서 다음 과 같 습 니 다.
int __init usb_add_config(struct usb_composite_dev *cdev,
		struct usb_configuration *config)
{
	int				status = -EINVAL;
	struct usb_configuration	*c;

	DBG(cdev, "adding config #%u '%s'/%p
", config->bConfigurationValue, config->label, config); if (!config->bConfigurationValue || !config->bind) goto done; /* Prevent duplicate configuration identifiers */ list_for_each_entry(c, &cdev->configs, list) { if (c->bConfigurationValue == config->bConfigurationValue) { status = -EBUSY; goto done; } } /*--------------------------------------------- ------------------------------------------*/ config->cdev = cdev; list_add_tail(&config->list, &cdev->configs); // USB , INIT_LIST_HEAD(&config->functions); // functions ,functions struct usb_function , , USB config->next_interface_id = 0; status = config->bind(config); // sourcesink_bind_config, struct usb_function , functions , if (status < 0) { //status 0 list_del(&config->list); config->cdev = NULL; } else { // unsigned i; // DBG(cdev, "cfg %d/%p speeds:%s%s
", config->bConfigurationValue, config, config->highspeed ? " high" : "", config->fullspeed ? (gadget_is_dualspeed(cdev->gadget) ? " full" : " full/low") : ""); //MAX_CONFIG_INTERFACES , composite.h , 16。 16 , , for (i = 0; i < MAX_CONFIG_INTERFACES; i++) { struct usb_function *f = config->interface[i]; if (!f) continue; DBG(cdev, " interface %d = %s/%p
", i, f->name, f); } } /* set_alt(), or next config->bind(), sets up * ep->driver_data as needed. */ usb_ep_autoconfig_reset(cdev->gadget); // cdev->gadget driver_data done: if (status) DBG(cdev, "added config '%s'/%u --> %d
", config->label, config->bConfigurationValue, status); return status; }
        이 함 수 는 설정 을 초기 화하 고 설정 을 장치 와 연결 시 키 며 디 버 깅 정 보 를 인쇄 합 니 다.이 장 치 는 설정 되 어 있 지만, 우 리 는 USB 장치 의 설정 아래 인터페이스의 집합 이라는 것 을 안다.그래서 함수 호출 config - > bind (config) 설정 에 인 터 페 이 스 를 추가 합 니 다.이 함 수 는 다음 과 같다.
static int __init sourcesink_bind_config(struct usb_configuration *c)
{
	struct f_sourcesink	*ss;
	int			status;

	ss = kzalloc(sizeof *ss, GFP_KERNEL);
	if (!ss)
		return -ENOMEM;

	ss->function.name = "source/sink";
	ss->function.descriptors = fs_source_sink_descs;
	ss->function.bind = sourcesink_bind;
	ss->function.unbind = sourcesink_unbind;
	ss->function.set_alt = sourcesink_set_alt;
	ss->function.disable = sourcesink_disable;

	status = usb_add_function(c, &ss->function);
	if (status)
		kfree(ss);
	return status;
}
        이 함수 가 할당 되 고 struct f 를 초기 화 한 것 을 알 수 있 습 니 다.sourcesink 구조 체, 이 구조 체 는 인 터 페 이 스 를 대표 하 는 struct usb 를 포함 합 니 다.function。그리고 struct usb 초기 화function 의 반전 함수.마지막 usb 호출add_function(c, &ss->function);설정 에 인 터 페 이 스 를 추가 합 니 다.usb_add_function 함 수 는 다음 과 같다.
int __init usb_add_function(struct usb_configuration *config,
		struct usb_function *function)
{
	int	value = -EINVAL;
        //      
	DBG(config->cdev, "adding '%s'/%p to config '%s'/%p
", function->name, function, config->label, config); // if (!function->set_alt || !function->disable) goto done; // function->config = config; list_add_tail(&function->list, &config->functions); /* REVISIT *require* function->bind? */ if (function->bind) { // function bind , function bind ,sourcesink_bind。 value = function->bind(config, function); if (value < 0) { list_del(&function->list); function->config = NULL; } } else value = 0; /* We allow configurations that don't work at both speeds. * If we run into a lowspeed Linux system, treat it the same * as full speed ... it's the function drivers that will need * to avoid bulk and ISO transfers. */ if (!config->fullspeed && function->descriptors) config->fullspeed = true; if (!config->highspeed && function->hs_descriptors) config->highspeed = true; done: if (value) DBG(config->cdev, "adding '%s'/%p --> %d
", function->name, function, value); return value; }
        우 리 는 이 함수 의 가장 중요 한 것 은 인터페이스 와 설정 을 연결 하 는 것 을 볼 수 있다.또한 인터페이스의 bind 함 수 를 호출 합 니 다. zero sourcelink 가 설정 한 인터페이스의 bind 는 sourcelink 입 니 다.bind。다음 정의:
static int __init
sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
{
	struct usb_composite_dev *cdev = c->cdev;
	struct f_sourcesink	*ss = func_to_ss(f);
	int	id;

	/* allocate interface ID(s) */
	id = usb_interface_id(c, f);
	if (id < 0)
		return id;
	source_sink_intf.bInterfaceNumber = id;
        //usb_interface_id(c, f)        config->next_interface_id    16    ,    config->interface[id] = f,  config->next_interface_id 1  
	/* allocate endpoints */
        //       ,      USB  。USB     USB  ,   USB  ,   USB     ,  zero sourcesink     ,          ,  In    out  
	ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
	if (!ss->in_ep) {
autoconf_fail:
		ERROR(cdev, "%s: can't autoconfigure on %s
", f->name, cdev->gadget->name); return -ENODEV; } ss->in_ep->driver_data = cdev; /* claim */ ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc); if (!ss->out_ep) goto autoconf_fail; ss->out_ep->driver_data = cdev; /* claim */ /* support high speed hardware */ if (gadget_is_dualspeed(c->cdev->gadget)) { hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; f->hs_descriptors = hs_source_sink_descs; } DBG(cdev, "%s speed %s: IN/%s, OUT/%s
", gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", f->name, ss->in_ep->name, ss->out_ep->name); return 0; }
        이 함 수 는 인터페이스의 인터페이스 id 를 초기 화 하 는 것 을 제외 합 니 다.또 인터페이스 에 점 을 분배 했다.이것 도 각 층 통합 의 마지막 단계 다.zero sourcesink 에는 인터페이스 설정 이 있 습 니 다.이 인 터 페 이 스 는 두 개의 점 이 있 고, 하 나 는 in 점 이 며, 하 나 는 Out 점 이다.usb_ep_autoconfig 함 수 는 할당 점 의 임 무 를 맡 았 습 니 다. 그 는 epautoconf. c 에 정의 되 었 습 니 다. 이 파일 은 헤더 파일 형식 으로 zero. c 에 포함 되 어 있 습 니 다.이 함수 에는 두 개의 인자 가 있 는데 하 나 는 struct usb 입 니 다.gadget 형식의 지침, 하 나 는 struct usbendpoint_descriptor 형식의 포인터, 즉 점 설명자 입 니 다. 이 함 수 는 점 설명자 의 정보 에 따라 자동 으로 struct usb 에 있 습 니 다.gadget 에서 적당 한 점 을 찾 습 니 다.
        위의 중 함수 호출 을 통 해 지금 은 설비 가 꽉 찼 습 니 다. 설정 도 있 고 인터페이스 도 있 습 니 다. 인터페이스 에 도 해당 하 는 점 이 있 습 니 다.각 층 의 관계 도 모두 연결 되 었 다.근 데 좀 어 지 러 워 요.확실히 이렇게 많은 함수 가 호출 되 었 으 니 어 지 럽 지 않 아 도 방법 이 없다.괜찮아, 우 리 는 각 함수 간 의 호출 관계 와 각 부분의 통합 과정 을 다시 정리 해 보 자.이 통합 과정 은 크게 두 가지 과정 으로 나 뉜 다.
(1) 프로 세 스 방향 Gadget 기능 구동 층 - > USB 장치 층 - > UDC 층.
         네 개의 데이터 구 조 를 바탕 으로: struct usbcomposite_driver struct usb_composite_dev struct usb_gadget_driver struct usb_gadget 
         두 register 함 수 를 가이드 로: usbcomposite_register(&zero_driver) usb_gadget_register_driver(&composite_driver)
(2) 프로 세 스 방향 UDC 층 - > USB 장치 층 - > Gadget 기능 구동 층
         네 개의 bind 함 수 는 직렬 점 으로 일련의 데이터 구조 와 초기 화 를 가 져 옵 니 다.이 네 개의 bind 함수 분 배 는:
         USB 장치 층 의 compositebid 는 UDC 층 의 usbgadget_register_driver 함수 호출.기능 은 struct usb 분배composite_dev cdev 를 초기 화 합 니 다.struct usb_composite_dev 구 조 는 UDC 층 의 usb 를 연결 합 니 다.gadget 와 Gadget 기능 구동 층 의 usbcomposite_driver。다음 상층 의 bind 를 호출 합 니 다.
         Gadget 기능 구동 층 의 zerobind 이 함수 의 주요 임 무 는 Gadget 기능 구동 층 의 USB 장치 정보 로 struct usb 를 초기 화 하 는 것 입 니 다.composite_dev 구조.그리고 다음 두 개의 bind 함 수 를 끌 어 냅 니 다.
         다른 두 개의 bid 함 수 는 모두 USB 장치 정보 와 관련 이 있 습 니 다. 하 나 는 설정 을 추가 할 때 호출 되 고 하 나 는 인 터 페 이 스 를 추가 할 때 호출 됩 니 다.이 두 함 수 는 sourcesinkadd 끌 어 내기.usb_add_config 설정 을 장치 에 추가 하여 config - > bid: sourcelinkbind_config. 이 bind 분배 및 인터페이스 초기 화, usb 호출add_function 설정 에 인 터 페 이 스 를 추가 합 니 다. usbadd_function 인출 function - > bind: sourcesinkbid 는 기능 에 따라 gadget 에서 적당 한 점 을 찾 습 니 다.그리고 struct usb 를 초기 화 합 니 다.composite_dev。우 리 는 이러한 bid 가 하나의 목적 이라는 것 을 발견 하고 struct usb 를 초기 화 합 니 다.composite_dev 구조 로 점점 풍만 해 집 니 다.이 구 조 는 USB 장 치 를 대표 하기 때문이다.적당 한 초기 화 를 거 친 후에 야 설비 가 정확하게 작 동 할 수 있다.여러 겹 의 초기 화 를 거 쳐 3 층 이 마침내 한데 통합 되 었 다.이 3 층 은 결국 포만 한 struct usb 를 형성 했다.composite_dev 구조.이 구 조 는 USB 장치 가 작 동 하 는 각종 정 보 를 포함 하고 있다.포함: 설정, 인터페이스, 점 등.우 리 는 이 구 조 를 다시 한 번 살 펴 보 자.
struct usb_composite_dev {
	struct usb_gadget		*gadget; //     UDC  usb_gadget
	struct usb_request		*req;    //  0     ,          
	unsigned			bufsiz;

	struct usb_configuration	*config; //USB  

	/* private: */
	/* internals */
	struct usb_device_descriptor	desc;   //     
	struct list_head		configs; //USB    
	struct usb_composite_driver	*driver;  //     Gadget     
	u8				next_string_id;

	/* the gadget driver won't enable the data pullup
	 * while the deactivation count is nonzero.
	 */
	unsigned			deactivations;

	/* protects at least deactivation count */
	spinlock_t			lock;
};
        초기 화 장치 가 준비 되 어 있 습 니 다. mini 2440 을 USB 호스트 에 삽입 하면 장치 매 거 진 이 시 작 됩 니 다. 이것 은 호스트 와 장치 의 통신 과 관련 됩 니 다.나중에 USB 장치 매 거 와 데이터 전송 과정 을 분석 하 겠 습 니 다.리 눅 스 USB Gadget 은 3 층 소프트웨어 구조 지만그러나 UDC 층 과 Gadget 기능 구동 층 만 모듈 로 커 널 에 등록 되 어 있다.USB 장치 계층 만 관련 된 파일 coposite. c 는 헤더 파일 형식 으로 각종 Gadget 기능 구동 에 포함 되 어 있 습 니 다.예전 에 커 널 코드 는 USB 장치 층 이 없 었 습 니 다.모든 Gadget 기능 구동 은 USB 장치 와 관련 된 세부 사항 을 스스로 처리 해 야 하 며 코드 중 복 률 이 높 기 때문에 이 USB 장치 층 이 나타 나 코드 의 중용 성 을 증가 시 킵 니 다.composite 는 말 그대로 재 활용 이라는 뜻 으로 원인 을 위해 이름 을 지 었 는 지 모르겠다.

좋은 웹페이지 즐겨찾기