GCT GDM72xx WiMAX chip (5)

gdm_usb.c で定義されてる gdm_usb_receive 手続きについて掘削対応。

とりあえず

このあたり

static int gdm_usb_receive(void *priv_dev,
			void (*cb)(void *cb_data, void *data, int len),
			void *cb_data)
{
	struct usbwm_dev *udev = priv_dev;
	struct usb_device *usbdev = udev->usbdev;
	struct rx_cxt *rx = &udev->rx;
	struct usb_rx *r;
	unsigned long flags;

	if (!udev->usbdev) {
		dev_err(&usbdev->dev, "%s: No such device\n", __func__);
		return -ENODEV;
	}

昨晩確認したのですが、引数な priv_dev は gdm_usb_probe あたりで準備されます。usbdeb 属性については gdm_usb_probe に渡される struct usb_interface オブジェクトから interface_to usbdev 手続きで取得されたものが設定されているはず。
また、rx 属性についても gdm_usb_probe 手続きから呼び出されている init_usb 手続きで初期設定されてます。

  • rx->free_list および rx->used_list は INIT_LIST_HEAD で初期化
  • rx->lock は spin_lock_init 手続きで初期化
  • rx 自体は alloc_rx_struct 手続きで初期化
    • urb 属性と buf 属性なオブジェクトが生成されてますね

初期化自体は済んでいるので struct rx_cxt 型な udev->rx から struct usb_rx オブジェクトを取り出しています。spin_lock 付き。

	spin_lock_irqsave(&rx->lock, flags);
	r = get_rx_struct(rx);
	spin_unlock_irqrestore(&rx->lock, flags);

get_rx_struct 手続きで何をしているか、というと基本的には free_list 属性から struct usb_rx 型な要素を取り出して云々、なのか (引用略)。
で、後は引数でもらってきた callback な関数ポインタと struct nic なオブジェクトを設定して

	r->callback = cb;
	r->cb_data = cb_data;

usb_fill_bulk_urb 手続きを呼び出して urb な要求を submit しているのか。

	usb_fill_bulk_urb(r->urb,
			usbdev,
			usb_rcvbulkpipe(usbdev, 0x82),
			r->buf,
			RX_BUF_SIZE,
			gdm_usb_rcv_complete,
			r);

	return usb_submit_urb(r->urb, GFP_ATOMIC);

こいつらが具体的に何を要求しているのか、は今から確認となります。

urb 要求

そもそもこの usb_fill_bulk_urb という手続きが何なのか、という話なんですが、とりあえず手続き定義のコメントを確認してみます。

 * usb_fill_bulk_urb - macro to help initialize a bulk urb
 * @urb: pointer to the urb to initialize.
 * @dev: pointer to the struct usb_device for this urb.
 * @pipe: the endpoint pipe
 * @transfer_buffer: pointer to the transfer buffer
 * @buffer_length: length of the transfer buffer
 * @complete_fn: pointer to the usb_complete_t function
 * @context: what to set the urb context to.
 *
 * Initializes a bulk urb with the proper information needed to submit it
 * to a device.

あ、思いだした。この手続きは第一引数な urb オブジェクトに以降の引数を設定する手続きでした。手続き部分のみ引用してみます。

	urb->dev = dev;
	urb->pipe = pipe;
	urb->transfer_buffer = transfer_buffer;
	urb->transfer_buffer_length = buffer_length;
	urb->complete = complete_fn;
	urb->context = context;

以下なカンジになるのか。

  • urb->dev には usbdev
  • urb->pipe には usb_rcvbulkpipe(usbdev, 0x82)
  • urb->transfer_buffer には r->buf
  • urb->transfer_buffer_length には RX_BUF_SIZE
  • urb->complete には gdm_usb_rcv_complete
  • urb->context には r

セットするだけ、ということはやっぱ次の usb_submit_urb がキモなのか。

	return usb_submit_urb(r->urb, GFP_ATOMIC);

手続き定義のコメントがやたらに長い。つうか結局ここが核心なのか。とりあえず urb.c の usb_submit_urb な手続き定義のコメント確認します。