dev_* に渡す struct device なオブジェクト

とりあえず pl2303.c をざっくり確認。あとusb-serial.c も見てみた方が良さげ。
あと、usb に偏ってしまうので他のソレも確認してみたくはあります。

pl2303.c

順に列挙してみます。

引数に struct usb_serial 型のポインタ

struct usb_serial *serial な定義で受け取っているとして dev_* には &serial->dev->dev を渡しています。struct usb_serial 型の定義を確認してみるに

struct usb_serial {
	struct usb_device		*dev;

で、struct usb_device 型で

	struct device dev;

という属性を持っていてこれを使っている模様。

引数に struct usb_device 型のポインタ

struct usb_device *dev な定義で受け取っているとして dev_* には &dev->dev を渡しています。これは上の例と同様。

引数に struct usb_serial_port 型のポインタ

struct usb_serial_port *port な定義で受け取っているとして dev_* には &port->dev を渡しています。struct usb_serial_port 型でも以下な形で struct device な属性が定義されております。

	struct device		dev;
};
引数に struct tty_struct 型のポインタ

struct tty_struct *tty な定義で受け取っているとして dev_* には何を渡しているか、というと一旦 struct tty_struct の driver_data という属性から struct usb_serial_port 型のオブジェクトを取り出して

	struct usb_serial_port *port = tty->driver_data;

上で使っているように struct device 型な属性を使っていますね。dev_* には &port->dev を渡しています。

引数に struct urb 型のポインタ

struct urb *urb な定義で受け取っているとして、これも一旦 struct usb_serial_port 型のオブジェクトを取り出して使っています。ちなみに struct urb 型の定義を見てみるに

	void *context;			/* (in) context for completion */

という属性があり、

	struct usb_serial_port *port =  urb->context;

という形で取り出して &port->dev を dev_* に渡している模様。ちょっとここはイレギュラーなのかどうなのか。struct urb 型なソレのみが渡されるパターンは結構見ている気がしているので別なソレを見てみる必要はありそげ。

usb-serial.c

で、usb-serial を見てみると少々方法が違ってたりして。
例えば struct tty_struct から取り出すのに直接だったりとか

	dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);

struct usb_device の場合は同じですね。

static struct usb_serial *create_serial(struct usb_device *dev,
/* snip */
	if (!serial) {
		dev_err(&dev->dev, "%s - out of memory\n", __func__);

struct usb_interface 型は初、な模様。

static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
						struct usb_interface *intf)
{
	const struct usb_device_id *id;

	id = usb_match_id(intf, drv->id_table);
	if (id) {
		dev_dbg(&intf->dev, "static descriptor matches\n");
		goto exit;

ええと、これも struct device な属性を持ってらっしゃいますね。

	struct device dev;		/* interface specific device info */

むむ。ちょっと出てきた構造体を列挙しておきます。

  • struct usb_serial
  • struct usb_device
  • struct usb_serial_port
  • struct tty_struct
  • struct urb
  • struct usb_interface
  • struct device

これはこれは、というカンジ。て、pl2303 なソレは gregkh さんが書いてるんすね。順に定義を確認してみます。

usb_serial

コメントによれば

usb_serial - structure used by the usb-serial core for a device

とのこと。構造体な属性に着目してみると保持しているのは以下。

	struct usb_device		*dev;
	struct usb_serial_driver	*type;
	struct usb_interface		*interface;
	struct usb_serial_port		*port[MAX_NUM_PORTS];
	struct kref			kref;
	struct mutex			disc_mutex;

struct usb_device と struct usb_interface あたりとの関係がアレ。

usb_device

コメントによれば

struct usb_device - kernel's representation of a USB device

とのこと。USB 全般ですね。属性として当り前ですが struct device な属性を持っていますのでこれを dev_* に渡して差し上げれば良い模様。
ちなみに struct usb_serial は struct usb_device 経由で struct device なオブジェクトを取得していました。
あと、微妙に気になるのが

	struct usb_device *parent;

な属性。子供な属性は無いなぁ、と思いつつ include/linux/usb.h を見てたら構造体定義の下に以下な手続きが定義されてました。

static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf)
{
	return to_usb_device(intf->dev.parent);
}

ちょいフライングで struct usb_interface を、って思ったら usb_interface の dev という属性は struct device でした。
ちなみに struct usb_device のコメントによれば以下とのこと。

@parent: our hub, unless we're the root

そりゃそうか的記述。ちなみに struct device の parent なコメントは

@parent: The device's "parent" device, the device to which it is attached.
         In most cases, a parent device is some sort of bus or host
         controller. If parent is NULL, the device, is a top-level device,
         which is not usually what you want.

あら? struct usb_interface って一体何なのだろうな。

usb_interface

乗りかかった船なので。構造体定義部分のコメントが以下。

struct usb_interface - what usb device drivers talk to

なので interface なのかどうなのか。ちなみに dev_* に渡す場合は struct usb_interface の dev 属性で良いらしい。あ、これは pl2303 には出てこないな。

struct usb_serial_port

こいつは serial という struct usb_serial な属性を持っているのでそれを取り出して、と思ったら struct device な dev 属性を渡してますね。
このヒトは何を表現するデータ構造かというと

usb_serial_port: structure for the specific ports of a device.

とのこと。確かに dev 属性は struct device へのリンクであり得ますね。

struct tty_struct

これ、以下な形で dev_* に渡されています。

static int pl2303_ioctl(struct tty_struct *tty,
			unsigned int cmd, unsigned long arg)
{
	struct serial_struct ser;
	struct usb_serial_port *port = tty->driver_data;

	dev_dbg(&port->dev, "%s cmd = 0x%04x\n", __func__, cmd);

一旦 struct usb_serial_port なオブジェクトを取り出して云々。driver_data 属性は void * な定義ですね。

	void *driver_data;

これ、usb-serial.c 見てみると serial_install 手続きで usb_serial_port なオブジェクトが設定されてます。これ、struct tty_operations な関数ポインタ属性の .install に設定されている模様。
これは usbserial なお約束という理解で良いはず。

struct urb

これは以下な形で struct usb_serial_port オブジェクトを取得して

static void pl2303_read_int_callback(struct urb *urb)
{
	struct usb_serial_port *port =  urb->context;

使ってます。

		dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n",
			__func__, status);

context 属性も void * で定義されてますね。これはどのレイヤで設定されるのか不明。ちなみにこの urb というソレが何かというと定義のコメントによれば

struct urb - USB Request Block

コメントによれば URB は usb_alloc_urb という手続き呼び出してオブジェクトが生成されて云々とあります。usb-serial.c の usb_serial_probe 手続きで呼び出されてます。でも、ここと struct urb オブジェクトの context 属性とは全く別ですな。
む、構造体定義なコメントに以下な記述があるな。

 * The context field is normally used to link URBs back to the relevant
 * driver or request state.

む、上記の pl2303_read_int_callback 手続きって struct usb_serial_driver な .read_int_callback 属性に設定されておるのか。あ、おそらく usb-serial.c の usb_serial_probe の中でアロケートした後で

			port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);

usb_fill_int_urb という手続きにポインタが渡されてるな。

			usb_fill_int_urb(port->interrupt_in_urb, dev,
				usb_rcvintpipe(dev,
						endpoint->bEndpointAddress),
				port->interrupt_in_buffer, buffer_size,
				serial->type->read_int_callback, port,
				endpoint->bInterval);

なんというか贅を尽くした造りですね。で、根拠を発見。手続き定義は以下なんですが

static inline void usb_fill_int_urb(struct urb *urb,
				    struct usb_device *dev,
				    unsigned int pipe,
				    void *transfer_buffer,
				    int buffer_length,
				    usb_complete_t complete_fn,
				    void *context,
				    int interval)
{
	urb->dev = dev;
	urb->pipe = pipe;
	urb->transfer_buffer = transfer_buffer;
	urb->transfer_buffer_length = buffer_length;
	urb->complete = complete_fn;
	urb->context = context;
	if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER)
		urb->interval = 1 << (interval - 1);
	else
		urb->interval = interval;
	urb->start_frame = -1;
}

port なオブジェクトが context 属性にセットされてますね。いやはや。おそらくはここで設定される struct urb なオブジェクトが callback に渡されるのかな。
がしかし、struct urb が渡される場合、同じ形で掘削が必要なのか。でもぶっちゃけてしまうとこれ、struct urb なオブジェクトの dev 属性使えよ、って話になりそうな気がしてたりもするんですがどうなのだろうか。
このあたり USB なドライバでチャレンジしてみるのもアレかもしれません。

ちょっと

comedi な USB ドライバ掘削して色々ヤッてみようかな。