KNX Linux USB Driver

/*
 * A low-level driver for EIB/Konnex bus access through USB
 *
 * (c) 2005  Heinz W. Werntges and Vladimir Vinarski
 *
 * $Id: knx_usb_driver.c,v 1.3 2005/10/29 22:43:47 werntges Exp $
 *
 * Revision history:
 *
 * $Log: knx_usb_driver.c,v $
 * Revision 1.3  2005/10/29 22:43:47  werntges
 * HWW: Sample code ( main() ) added
 *
 * Revision 1.2  2005/10/25 20:51:30  werntges
 * HWW: knx_init() improved - Id's now checked if provided
 *
 * 2005-10-07  V 1.00 Derived from a precursor presented at KSC2005, Pisa
 *
 * License: Lesser GPL (see /http://www.gnu.org/licenses/ for details)
 */


#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <asm/types.h>


#ifndef HID_MAX_USAGES
#define HID_MAX_USAGES 1024
#endif


#include <linux/hiddev.h>


int getUsageCode_Out0( int );
int match_fail( const char*, short );


/*
 * Set ADD_MAIN to 1 in order to add a main() function with a little demo
 */
#define ADD_MAIN 0


#define READ_BUFFER_LENGTH 64


/* File-global */


unsigned long usageCode;


/*
 * In:      report  - The report buffer, size should be at least 63 bytes
 *          bufsize - Buffer size, the max. number of bytes to be passed
 *          fd      - The file descriptor as delivered by init()
 * Out:     report  - Filled with the received bytes
 *
 * Returns: Number of bytes read, or a negative number on error
 */


int knx_receive( char* report, int bufsize, int fd  )
{
    struct hiddev_event readBuffer[READ_BUFFER_LENGTH];
    int ret, n, i;


    ret = (int) read( fd, readBuffer, sizeof(readBuffer) );
    if( ret < 0 )
return ret;
    n = ret / sizeof(readBuffer[0]);
    for( i=0; i < n && i < bufsize; i++ )
report[i] = readBuffer[i].value;
    return n;
}




/*
 * In:      report  - The report buffer (always 64 bytes), including record_ID
 *          fd      - The file descriptor as delivered by init()
 * Out:     -
 *
 * Returns: 0 if ok, or the error code of a failed ioctl() call
 */


int knx_send( const char report[64], int fd  )
{
    int rc = 0, uindex;


    // send output report
    struct hiddev_usage_ref uref;
    struct hiddev_report_info rinfo;


    // always send 63 bytes, assume 0x01 (report_id) is prepended
    uref.report_id = *report++;  // report_id byte: special treatment
    uref.report_type = HID_REPORT_TYPE_OUTPUT;
    uref.field_index = 0;


    // uref.usage_code = 0xFFA10005;
    uref.usage_code = usageCode;


    for( uindex = 0; uindex < 63; uindex++ )
    {
   uref.usage_index = uindex;
   uref.value = *report++;
   if( (rc=ioctl( fd, HIDIOCSUSAGE, &uref )) != 0 )
   {
       return rc;
   }
    }
    rinfo.report_type = HID_REPORT_TYPE_OUTPUT;
    rinfo.report_id =  0x01;
    rinfo.num_fields = 1;
    if( (rc=ioctl( fd, HIDIOCSREPORT, &rinfo )) != 0 )
    {
   return rc;
    }
    return 0;
}




/*
 * In:      device path  - Typically, "/dev/usb/hiddev0"
 *          vendorId     - 4 hex digits passed as a string, e.g. "2c58"
 *          productId    - 4 hex digits passed as a string, see above
 *          versionId    - 4 hex digits passed as a string, see above
 * Out:     -
 *
 * Returns: A valid file descriptor as returned by open(), or < 0 on error
 */


int knx_init( const char* device_path, 
     const char* vendorId, 
     const char* productId,
     const char* versionId )
{
    int fd = open ( device_path, O_RDWR );
    if (fd < 0) return fd;


    if (getUsageCode_Out0( fd ) < 0) return -8;
    
    if (*vendorId != 0 || *productId != 0 || *versionId != 0) {
/*
* If vendorID, productId, or versionId provided:
*    Check if device matches them!
*/
struct hiddev_devinfo device_info;


int rc = ioctl( fd, HIDIOCGDEVINFO, &device_info );
if (rc < 0) return -16;


if ((*vendorId  != 0) && match_fail(vendorId,  device_info.vendor))
   return -4;
if ((*productId != 0) && match_fail(productId, device_info.product))
  return -4;
if ((*versionId != 0) && match_fail(versionId, device_info.version))
  return -4;
   
    }
    return fd;
}




/*
 * In:      fd  - The file descriptor of the currently opened device
 * Out:     -
 * Returns: 0 if ok, error code of close() if not
 */


int knx_exit( int fd )
{
   return close( fd );
}




/*
 * Internally used functions - don't export to Ruby!
 */


int getUsageCode_Out0( int fd )
{
    struct hiddev_usage_ref uref;
    int rc;


    uref.report_type = HID_REPORT_TYPE_OUTPUT;
    uref.report_id = 0x01;
    uref.field_index = 0;
    uref.usage_index = 0;
    rc = ioctl( fd, HIDIOCGUCODE, &uref );
    if (rc < 0) return rc;
    usageCode = uref.usage_code;
    return 0;
}




int match_fail( const char* id_string, short value )
{
    int id;


    sscanf( id_string, "%4x", &id );
    return (id == value) ? 0 : 1;
}


#if ADD_MAIN


/*
 * Some sample code to demonstrate usage
 * 
 * Task: Determine supported EMI mode(s) of USB interface
 */


#include <stdlib.h> 


#define RPT_SIZE 64


const unsigned char knxReportGetSupportedEMI_Types[] = {
    0x01,     // unsigned char  reportId;
    0x13,     // unsigned char  packetInfo;
    0x09,     // unsigned char  dataLength;
    0x00,     // unsigned char  protocolVersion;
    0x08,     // unsigned char  headerLength;
    0x00,0x01,// unsigned short bodyLength;
    0x0F,     // unsigned char  protocolId;
    0x01,     // unsigned char  emiId; // here: service Id
    0x00, 0x00,// unsigned short manufactureCode;
    0x01,     // unsigned char  emiMessageCode;
    // pad to 64 byte
    0,0,0,0,
    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
};


int main(int argc, char **argv) {


    int fd, rc;
    char receive_buffer[RPT_SIZE];


    fd = knx_init( "/dev/usb/hiddev0", "145c", "1330", "" );
    if (fd < 0) {
printf( "knx_init() failed with err code %d\n", fd );
exit(-1);
    }


    rc = knx_send( knxReportGetSupportedEMI_Types, fd );
    if (rc != 0) {
printf( "knx_send() failed with err code %d\n", rc );
exit(1);
    }
    /* Note: 
     *
     * If the following call blocks despite correct outgoing report,
     * consider to add a litte delay here (e.g. 50 ms).
     */
    rc = knx_receive( receive_buffer, RPT_SIZE, fd );
    if ( rc < 0 ) {
printf( "knx_receive() failed with err code %d\n", rc );
exit(2);
    }


    /* Expected result: 13 0B 00 08 00 03 0F 02 00 00 01 00 01 */


    short unsigned res = receive_buffer[11] << 8 | receive_buffer[12];
    printf ( "Result is %x\n", res);


    if (res & 1) printf( "EMI1 supported\n" );
    if (res & 2) printf( "EMI2 supported\n" );
    if (res & 4) printf( "cEMI supported\n" );


    printf( "Exiting...\n" );
    knx_exit( fd );    
    return 0;
}
#endif
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值