2017-01-05 7 views
-1

저는 Linux 디바이스 드라이버에 대한 멍청한 반응을 보입니다. i2c 드라이버 (클라이언트)를 구현하려고합니다. 내가 할 수있는 지점에서 (장치 트리 항목으로 인해) insmod, .probe이 호출되면서 .probe에서 장치에 읽고 쓸 수 있습니다. 큰.i2c 드라이버는 다른 문자 장치 드라이버와 마찬가지로 구현해야합니까?

그러나 사용자 공간에서 드라이버로 읽기/쓰기를 시작할 수 있어야합니다. 이렇게하기 위해서, i2c 드라이버는 다른 char 디바이스 드라이버처럼 형성되어야합니까? 의미는 사용자 공간이 file_operations이므로 open, close, read, writeioctls 일 수 있습니까?

필자가 본 모든 i2c 클라이언트 예제에서 아무도 내가 언급 한 이러한 것들을 구현하지 않았기 때문에 묻습니다. file_operations 구조체가 설정되지 않은 채 사용자 공간에서 호출을 시작한 방법에 대해 궁금합니다. 어쩌면 아무도 그것을 언급하지 않았을 것입니다, 나도 몰라요 ... i2c가 플랫폼 장치 드라이버라고 불리는 이유는이게 필요하지 않은지 궁금합니다. 누군가 나 자신을 추측하는 데 도움이된다는 것을 확인할 수 있다면.

내가 무엇을 요구하는지 이해한다면 나머지는 무시하십시오. 당신이 내 질문에 대해 혼란스러워하는 경우 여기에 내가 부탁 해요 무엇보다 구체적인 설명은 다음과 같습니다

내가 지금이 : 다음과 같은 요소를 추가해야 할 경우

static int device_probe(struct i2c_client   *client, 
         const struct i2c_device_id *id) 
{ 
    struct device  *dev = &client->dev; 
    struct device_data *data; 

    /* Check the functionality of the i2c-adapter for smbus byte read/write */ 
    if (!i2c_check_functionality(client->adapter, 
           I2C_FUNC_SMBUS_BYTE_DATA)) 
    { 
     printk(KERN_ALERT "%s %d: device required i2c functionality is not supported\n", __func__, __LINE__); 
     return -ENODEV; 
    } 

    /* Allocate memory to hold the device data 
    * Using devm_kzalloc so do not have to worry about kfree */ 
    data = devm_kzalloc(dev, sizeof(struct device_data), GFP_KERNEL); 
    if (dev == NULL) 
    { 
     printk(KERN_ALERT "%s %d: no memory\n", __func__, __LINE__); 
     return -ENOMEM; 
    } 

    /* Record the pointer to current client */ 
    data->device_i2c_client = client; 

    /* Set the client's data field to point to device-specific data struct */ 
    i2c_set_clientdata(client, data); 

    /* Add the device-specific data struct to our collection of device client devices */ 
    device_data_tbl[id->driver_data] = data; 

    /* Do a read, test the access */ 
    device_read(); 

    return 0; 
} 

static int device_remove(struct i2c_client *client) 
{ 
    return 0; 
} 


int device_read(uint8_t    device_device_id, 
       uint16_t const  dev_reg_addr, 
       uint8_t *const  read_val) 
{ 
    /* some read access */ 
} 

static struct i2c_device_id device_idtable[] = { 
    { "si5342", 0 }, 
    { }, 
}; 
MODULE_DEVICE_TABLE(i2c, device_idtable); 

static struct i2c_driver device_driver = { 
    .driver = { 
    .name = device_DRIVER_NAME, 
     .owner = THIS_MODULE 
    }, 
    .id_table = device_idtable, 
    .probe  = device_probe, 
    .remove  = device_remove, 
}; 

static int __init device_driver_init(void) 
{ 
    return i2c_add_driver(&device_driver); 
} 
module_init(device_driver_init); 


static void __exit device_driver_exit(void) 
{ 
    return i2c_del_driver(&device_driver); 
} 
module_exit(device_driver_exit); 

가 궁금

static struct file_operations oxdrv_fops = 
{ 
    .owner = THIS_MODULE, 
    .release = device_release, 
    .open = device_open, 
    .unlocked_ioctl = device_ioctl 
}; 

/* Associated function definitions: device_open, device_ioctl, etc */ 

alloc_chrdev_region(); 
cdev_init(); 
+0

예, 너무 분명합니다. 드라이버는 특별히 고안된 API를 통해 I2C * 호스트 *와 * 클라이언트 * 사이에서 통신이 이루어지기 때문에 필요하지 않습니다. 단 하나의 드라이버 만 슬레이브와 사용자 공간 통신을 직접 구현하므로 분명히 필요하지 않습니다. – 0andriy

+0

죄송합니다, 무슨 뜻인지 잘 모르겠습니다. 사용자 공간에서 내 드라이버에 대한 읽기/쓰기를 시작할 수 있어야합니다. 그래서 ioctls가 필요하다고 생각합니다. 사용자 공간이 장치 드라이버 동작을 트리거하는 다른 방법을 알지 못합니다. "통신이 특수하게 고안된 API를 통해 I2C 호스트와 클라이언트간에 발생했습니다"라는 것이 무엇을 의미하는지 확신 할 수 없습니다. 어떤 API를 특별히 고안 했습니까? – Splaty

+0

기존 I2C_DEV 드라이버 만 사용하십시오. 사용자 공간에서 I2C * 클라이언트 * 로의 원시 통신에만 특별히 설계되었습니다. – 0andriy

답변

0

은 내가 @Alexandre Belloni가의 코멘트와 함께 더 나은 지금 장치 드라이버 모델을 이해하고 프레젠테이션 슬라이드의 세트를 읽고 생각 : http://free-electrons.com/doc/training/linux-kernel/linux-kernel-slides.pdf.

  1. 문자
  2. 네트워크
  3. 블록

그러나, "프레임 워크 특정있다 : 관련 슬라이드 장치 드라이버의 3 종류가 있습니다 페이지 221에서 236

에 있습니다 "는 동일한 유형의 장치 용 드라이버의 공통 부분을 구현하는 문자 장치 드라이버의 하위 클래스로 존재합니다.

예를 들어, 하드웨어 모니터링에 사용되는 마더 보드의 온도 센서는 hwmon 프레임 워크 (https://www.kernel.org/doc/Documentation/hwmon/hwmon-kernel-api.txt) 아래에 등록됩니다. i2c probe, read, write 기능을 구현하지만 file_operations struct 문자 장치로 구성하는 대신 hwmon 장치로 등록하면됩니다 (hwmon_device_register_with_groups()). 사용자 공간에 노출 시키려면 attributes을 사용하여 /sys/class/hwmon/hwmon* 디렉토리를 빌드하고 원하는 노출/읽기 명령 목록 (예 : 채널 1에서 임시 읽기, 임시 온도 레지스터로 쓰기)을 작성해야합니다.

커널을 빌드 할 때 make menuconfig에서 장치를 선택하여 커널과 함께 빌드하십시오. 이렇게하면 커널을 부팅하면 장치가 /sys/class/hwmon/hwmon* 아래에 표시되고 userspace는과 read이고 sysfs 인터페이스를 통해 장치에서 사용할 수 있습니다. 좋은 예를 여기에서보십시오 : http://lxr.free-electrons.com/source/drivers/hwmon/tmp421.c. 또는 hwmon 디렉토리의 모든 장치.

그래서 내 혼란이있었습니다. @Alexandre Belloni가 지적했듯이 이러한 장치는 프레임 워크 아래에 등록되므로 명시 적 문자 장치 드라이버 코드는 필요하지 않습니다. 나에게 이것은 사실이 아니기 때문에, 내가하고있는 장치 (클럭킹 PLL)에 적합한 프레임 워크가 없다고 생각한다. 따라서 일반적인 경로를 따라 가면서 캐릭터 장치로 구현해야합니다. 이것은 커널 부팅 중에 자동으로로드되는 것이 아니라 모듈로로드/언로드 할 수도 있습니다.

내가 실수 한 부분을 바로 수정하십시오. 나는 이것이 i2c-clients를 작성하는 것에 대해 혼란 스러울 때 도움이되기를 바랍니다.

+1

일반적인 클럭 프레임 워크 (드라이버 clk)는 클럭 및 PLL을위한 프레임 워크입니다. 그러나 사용자 공간에서 PLL을 사용하여 수행 할 수있는 작업을 확신 할 수 없으므로 이것이 적합하지 않을 수 있습니다. –

+0

@AlexandreBelloni. 제안 해 주셔서 감사합니다. https://www.kernel.org/doc/Documentation/clk.txt를 읽은 후에는 내가하고 싶은 일에 적합하지 않다고 생각합니다. 도움을 감사하십시오. – Splaty

+0

IIO 프레임 워크에는 일부 클럭 칩 드라이버가 있습니다. clk는 SoC의 일부에 클럭을 제공하는 드라이버에서 사용됩니다. 그것은 다른 커널 드라이버에 의해 그들이 구동하는 것에 대한 시계를 활성화/비활성화하는 데 사용됩니다. IIO clockgen은 사용자 공간 제어를 허용하며 다른 드라이버에 클록을 제공하지 않습니다. – TrentP