LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* led and hid class - hid_device vs led_classdev
@ 2008-11-04  7:51 Adam Nielsen
  2008-11-04 21:48 ` Jiri Slaby
  0 siblings, 1 reply; 7+ messages in thread
From: Adam Nielsen @ 2008-11-04  7:51 UTC (permalink / raw)
  To: LKML Mailinglist

Hi all,

I'm writing a driver for a USB HID device (using the new hid class), but 
I'm a bit confused about how the hid_device structure relates to the 
other driver-information structures.

One of the functions the device implements is a LED.  This is pretty 
simple to control (basic on/off), so I'd like to implement a device in 
the "led" class that controls this led.

In my hid driver's probe function I'm given a struct hid_device* which 
is used with functions like hid_hw_start().

I then need to call led_classdev_register() to register my led device. 
At the moment I pass this function hid_device.dev

Then I set my custom driver data with hid_set_drvdata().

Later on, when the user wants to switch the LED on or off, a function in 
my driver gets called, with a struct led_classdev* parameter.

I'm stuck trying to figure out how to convert this led_classdev 
parameter back into a hid_device, so that I can extract the custom data 
I set with hid_set_drvdata().

Some of the led drivers use platform_set_drvdata() in their probe 
functions to get their custom data instead, but I'm afraid if I do this 
I'll overwrite any hid-related data that hid_set_drvdata() might tack on 
to my custom data.

Some pseudocode to help illustrate:

static int my_probe(struct hid_device *hid,
   const struct hid_device_id *id)
{
   hid_parse(hid);
   hid_hw_start(hid, HID_CONNECT_DEFAULT);

   led_classdev_register(&hid->dev, &my_led);

   hid_set_drvdata(hid, my_data);

   /* Don't want to use this, in case it overwrites something that
      hid_set_drvdata() includes. */
   /*platform_set_drvdata(&hid->dev, my_data);*/
}

/* Callback function when user wants to change LED state */
static void my_led_set(struct led_classdev *led_cdev,
   enum led_brightness value)
{
   /* How do I get my_data back? */
}

Hopefully this explains what I'm after - if you need me to clarify 
anything please let me know.

Many thanks,
Adam.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: led and hid class - hid_device vs led_classdev
  2008-11-04  7:51 led and hid class - hid_device vs led_classdev Adam Nielsen
@ 2008-11-04 21:48 ` Jiri Slaby
  2008-11-08  6:18   ` hid class and sysfs/hwmon (was: led and hid class - hid_device vs led_classdev) Adam Nielsen
  0 siblings, 1 reply; 7+ messages in thread
From: Jiri Slaby @ 2008-11-04 21:48 UTC (permalink / raw)
  To: Adam Nielsen; +Cc: LKML Mailinglist

On 11/04/2008 08:51 AM, Adam Nielsen wrote:
> /* Callback function when user wants to change LED state */
> static void my_led_set(struct led_classdev *led_cdev,
>   enum led_brightness value)
> {
>   /* How do I get my_data back? */
> }
> 
> Hopefully this explains what I'm after - if you need me to clarify
> anything please let me know.

my_led should by part of my_data, then you do
my_data = container_of(led_cdev, /*typeof(my_data)*/, my_led);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* hid class and sysfs/hwmon (was: led and hid class - hid_device vs led_classdev)
  2008-11-04 21:48 ` Jiri Slaby
@ 2008-11-08  6:18   ` Adam Nielsen
  2008-11-08 14:16     ` hid class and sysfs/hwmon Jiri Slaby
  0 siblings, 1 reply; 7+ messages in thread
From: Adam Nielsen @ 2008-11-08  6:18 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: LKML Mailinglist

>> static void my_led_set(struct led_classdev *led_cdev,
>>   enum led_brightness value)
>> {
>>   /* How do I get my_data back? */
>> }
>>
> 
> my_led should by part of my_data, then you do
> my_data = container_of(led_cdev, /*typeof(my_data)*/, my_led);

That did the trick, thanks!  I hadn't realised what container_of() was 
meant to be for - that's quite a useful little macro!

I got that working (can switch the LED on and off via the led device) 
but now I'm stuck trying to implement a hwmon interface for the device's 
sensors.

As far as I can tell I'm doing everything fine, but for some reason the 
hwmon interface gets created but with no files inside it (apart from a 
few defaults.)  It's supposed to have files like "temp1_input" to report 
temperatures, but these files never appear.

The only thing that I'm unsure of is the first parameter to 
sysfs_create_group().  All the other drivers use something like 
i2c_client.dev.kobj or platform_device.dev.kobj, but I'm using 
hid_device.dev.kobj.  I'm guessing that should work just as well, but I 
can't figure out why else the sysfs files never appear in the new hwmon 
folder in /sys/class/hwmon/

Here is the code so far, if it's useful: (I've omitted all the error 
checking code for clarity, all the functions called here return success)

--------------------------------------------
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);

static struct attribute *odin_attributes[] = {
   &sensor_dev_attr_temp1_input.dev_attr.attr,
   NULL
};

static const struct attribute_group odin_attr_group = {
   .attrs = odin_attributes,
};

static int odin_probe(struct hid_device *hdev,
   const struct hid_device_id *id)
{
   hid_parse(hdev);
   hid_hw_start(hdev, HID_CONNECT_DEFAULT);

   odin_psu = kzalloc(sizeof(struct odin_psu_device), GFP_KERNEL);
   odin_psu->hdev = hdev;

   hid_set_drvdata(hdev, odin_psu);

   sysfs_create_group(&hdev->dev.kobj, &odin_attr_group);
   odin_psu->hwmon_dev = hwmon_device_register(&hdev->dev);

   return 0;
}
--------------------------------------------
$ ls /sys/class/hwmon/hwmon5/
total 0
drwxr-xr-x 3 root root    0 2008-11-08 14:50 .
drwxr-xr-x 8 root root    0 2008-11-08 14:50 ..
lrwxrwxrwx 1 root root    0 2008-11-08 14:50 device -> 
../../../devices/pci0000:00/0000:00:1d.2/usb8/8-1/8-1:1.0/0003:1044:4001.0001
drwxr-xr-x 2 root root    0 2008-11-08 14:50 power
lrwxrwxrwx 1 root root    0 2008-11-08 14:50 subsystem -> ../../hwmon
-rw-r--r-- 1 root root 4.0K 2008-11-08 14:50 uevent
--------------------------------------------

If anyone can see why this might result in no sysfs files, please let me 
know!  I previously had most of this code working with a platform_device 
instead of the hid_device, which is what makes me wonder about 
hdev->dev.kobj.  (Not sure how to test if that variable is accurate, 
either.)  Or perhaps it has already been used elsewhere and it can only 
be used once?

Thanks,
Adam.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: hid class and sysfs/hwmon
  2008-11-08  6:18   ` hid class and sysfs/hwmon (was: led and hid class - hid_device vs led_classdev) Adam Nielsen
@ 2008-11-08 14:16     ` Jiri Slaby
  2008-11-08 21:45       ` Adam Nielsen
  0 siblings, 1 reply; 7+ messages in thread
From: Jiri Slaby @ 2008-11-08 14:16 UTC (permalink / raw)
  To: Adam Nielsen; +Cc: LKML Mailinglist

On 11/08/2008 07:18 AM, Adam Nielsen wrote:
> Here is the code so far, if it's useful: (I've omitted all the error
> checking code for clarity, all the functions called here return success)
> 
> --------------------------------------------
> static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
> 
> static struct attribute *odin_attributes[] = {
>   &sensor_dev_attr_temp1_input.dev_attr.attr,
>   NULL
> };
> 
> static const struct attribute_group odin_attr_group = {
>   .attrs = odin_attributes,
> };
> 
> static int odin_probe(struct hid_device *hdev,
>   const struct hid_device_id *id)
> {
>   hid_parse(hdev);
>   hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> 
>   odin_psu = kzalloc(sizeof(struct odin_psu_device), GFP_KERNEL);
>   odin_psu->hdev = hdev;
> 
>   hid_set_drvdata(hdev, odin_psu);
> 
>   sysfs_create_group(&hdev->dev.kobj, &odin_attr_group);
>   odin_psu->hwmon_dev = hwmon_device_register(&hdev->dev);
> 
>   return 0;
> }
> --------------------------------------------
> If anyone can see why this might result in no sysfs files, please let me
> know!  I previously had most of this code working with a platform_device
> instead of the hid_device, which is what makes me wonder about
> hdev->dev.kobj.  (Not sure how to test if that variable is accurate,
> either.)  Or perhaps it has already been used elsewhere and it can only
> be used once?

I suppose it's under /sys/bus/hid/devices/.../, isn't it?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: hid class and sysfs/hwmon
  2008-11-08 14:16     ` hid class and sysfs/hwmon Jiri Slaby
@ 2008-11-08 21:45       ` Adam Nielsen
  2008-11-08 21:51         ` Jiri Slaby
  0 siblings, 1 reply; 7+ messages in thread
From: Adam Nielsen @ 2008-11-08 21:45 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: LKML Mailinglist

>> If anyone can see why this might result in no sysfs files, please let me
>> know!  I previously had most of this code working with a platform_device
>> instead of the hid_device, which is what makes me wonder about
>> hdev->dev.kobj.  (Not sure how to test if that variable is accurate,
>> either.)  Or perhaps it has already been used elsewhere and it can only
>> be used once?
> 
> I suppose it's under /sys/bus/hid/devices/.../, isn't it?

Aha, yes!  I didn't even think of checking there.  I suppose this means 
I have to create another device (like a platform_device) in order to 
have the sysfs files appear in the correct place?

Is a platform_device the correct type to create, or is there another way?

Thanks,
Adam.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: hid class and sysfs/hwmon
  2008-11-08 21:45       ` Adam Nielsen
@ 2008-11-08 21:51         ` Jiri Slaby
  2008-11-08 22:02           ` Adam Nielsen
  0 siblings, 1 reply; 7+ messages in thread
From: Jiri Slaby @ 2008-11-08 21:51 UTC (permalink / raw)
  To: Adam Nielsen; +Cc: LKML Mailinglist

Adam Nielsen napsal(a):
>>> If anyone can see why this might result in no sysfs files, please let me
>>> know!  I previously had most of this code working with a platform_device
>>> instead of the hid_device, which is what makes me wonder about
>>> hdev->dev.kobj.  (Not sure how to test if that variable is accurate,
>>> either.)  Or perhaps it has already been used elsewhere and it can only
>>> be used once?
>>
>> I suppose it's under /sys/bus/hid/devices/.../, isn't it?
> 
> Aha, yes!  I didn't even think of checking there.  I suppose this means
> I have to create another device (like a platform_device) in order to
> have the sysfs files appear in the correct place?
> 
> Is a platform_device the correct type to create, or is there another way?

I don't know much about hwmon, but I would guess you should use hwmon_dev
for registering the attributes if you want it under /sys/class/hwmon/...

Such as:
sysfs_create_group(&odin_psu->hwmon_dev->kobj, &odin_attr_group);

No?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: hid class and sysfs/hwmon
  2008-11-08 21:51         ` Jiri Slaby
@ 2008-11-08 22:02           ` Adam Nielsen
  0 siblings, 0 replies; 7+ messages in thread
From: Adam Nielsen @ 2008-11-08 22:02 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: LKML Mailinglist

> I don't know much about hwmon, but I would guess you should use hwmon_dev
> for registering the attributes if you want it under /sys/class/hwmon/...
> 
> Such as:
> sysfs_create_group(&odin_psu->hwmon_dev->kobj, &odin_attr_group);
> 
> No?

Oh, that worked!  All the other hwmon drivers seem to have it the other 
way around, i.e. you attach sysfs to your original bus/class device kobj 
instead of the hwmon kobj.

Hopefully doing it this way won't have any side effects...

Thanks for your help Jiri!

Cheers,
Adam.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2008-11-08 22:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-04  7:51 led and hid class - hid_device vs led_classdev Adam Nielsen
2008-11-04 21:48 ` Jiri Slaby
2008-11-08  6:18   ` hid class and sysfs/hwmon (was: led and hid class - hid_device vs led_classdev) Adam Nielsen
2008-11-08 14:16     ` hid class and sysfs/hwmon Jiri Slaby
2008-11-08 21:45       ` Adam Nielsen
2008-11-08 21:51         ` Jiri Slaby
2008-11-08 22:02           ` Adam Nielsen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).