@@ -156,6 +156,7 @@ struct cp2112_device {
156156 wait_queue_head_t wait ;
157157 u8 read_data [61 ];
158158 u8 read_length ;
159+ u8 hwversion ;
159160 int xfer_status ;
160161 atomic_t read_avail ;
161162 atomic_t xfer_avail ;
@@ -446,33 +447,71 @@ static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
446447 return data_length + 3 ;
447448}
448449
450+ static int cp2112_i2c_write_read_req (void * buf , u8 slave_address ,
451+ u8 * addr , int addr_length ,
452+ int read_length )
453+ {
454+ struct cp2112_write_read_req_report * report = buf ;
455+
456+ if (read_length < 1 || read_length > 512 ||
457+ addr_length > sizeof (report -> target_address ))
458+ return - EINVAL ;
459+
460+ report -> report = CP2112_DATA_WRITE_READ_REQUEST ;
461+ report -> slave_address = slave_address << 1 ;
462+ report -> length = cpu_to_be16 (read_length );
463+ report -> target_address_length = addr_length ;
464+ memcpy (report -> target_address , addr , addr_length );
465+ return addr_length + 5 ;
466+ }
467+
449468static int cp2112_i2c_xfer (struct i2c_adapter * adap , struct i2c_msg * msgs ,
450469 int num )
451470{
452471 struct cp2112_device * dev = (struct cp2112_device * )adap -> algo_data ;
453472 struct hid_device * hdev = dev -> hdev ;
454473 u8 buf [64 ];
455474 ssize_t count ;
475+ ssize_t read_length = 0 ;
476+ u8 * read_buf = NULL ;
456477 unsigned int retries ;
457478 int ret ;
458479
459480 hid_dbg (hdev , "I2C %d messages\n" , num );
460481
461- if (num != 1 ) {
482+ if (num == 1 ) {
483+ if (msgs -> flags & I2C_M_RD ) {
484+ hid_dbg (hdev , "I2C read %#04x len %d\n" ,
485+ msgs -> addr , msgs -> len );
486+ read_length = msgs -> len ;
487+ read_buf = msgs -> buf ;
488+ count = cp2112_read_req (buf , msgs -> addr , msgs -> len );
489+ } else {
490+ hid_dbg (hdev , "I2C write %#04x len %d\n" ,
491+ msgs -> addr , msgs -> len );
492+ count = cp2112_i2c_write_req (buf , msgs -> addr ,
493+ msgs -> buf , msgs -> len );
494+ }
495+ if (count < 0 )
496+ return count ;
497+ } else if (dev -> hwversion > 1 && /* no repeated start in rev 1 */
498+ num == 2 &&
499+ msgs [0 ].addr == msgs [1 ].addr &&
500+ !(msgs [0 ].flags & I2C_M_RD ) && (msgs [1 ].flags & I2C_M_RD )) {
501+ hid_dbg (hdev , "I2C write-read %#04x wlen %d rlen %d\n" ,
502+ msgs [0 ].addr , msgs [0 ].len , msgs [1 ].len );
503+ read_length = msgs [1 ].len ;
504+ read_buf = msgs [1 ].buf ;
505+ count = cp2112_i2c_write_read_req (buf , msgs [0 ].addr ,
506+ msgs [0 ].buf , msgs [0 ].len , msgs [1 ].len );
507+ if (count < 0 )
508+ return count ;
509+ } else {
462510 hid_err (hdev ,
463511 "Multi-message I2C transactions not supported\n" );
464512 return - EOPNOTSUPP ;
465513 }
466514
467- if (msgs -> flags & I2C_M_RD )
468- count = cp2112_read_req (buf , msgs -> addr , msgs -> len );
469- else
470- count = cp2112_i2c_write_req (buf , msgs -> addr , msgs -> buf ,
471- msgs -> len );
472-
473- if (count < 0 )
474- return count ;
475-
476515 ret = hid_hw_power (hdev , PM_HINT_FULLON );
477516 if (ret < 0 ) {
478517 hid_err (hdev , "power management error: %d\n" , ret );
@@ -508,21 +547,34 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
508547 goto power_normal ;
509548 }
510549
511- if (!(msgs -> flags & I2C_M_RD ))
512- goto finish ;
513-
514- ret = cp2112_read (dev , msgs -> buf , msgs -> len );
515- if (ret < 0 )
516- goto power_normal ;
517- if (ret != msgs -> len ) {
518- hid_warn (hdev , "short read: %d < %d\n" , ret , msgs -> len );
519- ret = - EIO ;
520- goto power_normal ;
550+ for (count = 0 ; count < read_length ;) {
551+ ret = cp2112_read (dev , read_buf + count , read_length - count );
552+ if (ret < 0 )
553+ goto power_normal ;
554+ if (ret == 0 ) {
555+ hid_err (hdev , "read returned 0\n" );
556+ ret = - EIO ;
557+ goto power_normal ;
558+ }
559+ count += ret ;
560+ if (count > read_length ) {
561+ /*
562+ * The hardware returned too much data.
563+ * This is mostly harmless because cp2112_read()
564+ * has a limit check so didn't overrun our
565+ * buffer. Nevertheless, we return an error
566+ * because something is seriously wrong and
567+ * it shouldn't go unnoticed.
568+ */
569+ hid_err (hdev , "long read: %d > %zd\n" ,
570+ ret , read_length - count + ret );
571+ ret = - EIO ;
572+ goto power_normal ;
573+ }
521574 }
522575
523- finish :
524576 /* return the number of transferred messages */
525- ret = 1 ;
577+ ret = num ;
526578
527579power_normal :
528580 hid_hw_power (hdev , PM_HINT_NORMAL );
@@ -537,7 +589,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
537589 struct cp2112_device * dev = (struct cp2112_device * )adap -> algo_data ;
538590 struct hid_device * hdev = dev -> hdev ;
539591 u8 buf [64 ];
540- __be16 word ;
592+ __le16 word ;
541593 ssize_t count ;
542594 size_t read_length = 0 ;
543595 unsigned int retries ;
@@ -554,7 +606,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
554606 if (I2C_SMBUS_READ == read_write )
555607 count = cp2112_read_req (buf , addr , read_length );
556608 else
557- count = cp2112_write_req (buf , addr , data -> byte , NULL ,
609+ count = cp2112_write_req (buf , addr , command , NULL ,
558610 0 );
559611 break ;
560612 case I2C_SMBUS_BYTE_DATA :
@@ -569,7 +621,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
569621 break ;
570622 case I2C_SMBUS_WORD_DATA :
571623 read_length = 2 ;
572- word = cpu_to_be16 (data -> word );
624+ word = cpu_to_le16 (data -> word );
573625
574626 if (I2C_SMBUS_READ == read_write )
575627 count = cp2112_write_read_req (buf , addr , read_length ,
@@ -582,7 +634,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
582634 size = I2C_SMBUS_WORD_DATA ;
583635 read_write = I2C_SMBUS_READ ;
584636 read_length = 2 ;
585- word = cpu_to_be16 (data -> word );
637+ word = cpu_to_le16 (data -> word );
586638
587639 count = cp2112_write_read_req (buf , addr , read_length , command ,
588640 (u8 * )& word , 2 );
@@ -675,7 +727,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
675727 data -> byte = buf [0 ];
676728 break ;
677729 case I2C_SMBUS_WORD_DATA :
678- data -> word = be16_to_cpup (( __be16 * )buf );
730+ data -> word = le16_to_cpup (( __le16 * )buf );
679731 break ;
680732 case I2C_SMBUS_BLOCK_DATA :
681733 if (read_length > I2C_SMBUS_BLOCK_MAX ) {
@@ -1030,6 +1082,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
10301082 dev -> adap .dev .parent = & hdev -> dev ;
10311083 snprintf (dev -> adap .name , sizeof (dev -> adap .name ),
10321084 "CP2112 SMBus Bridge on hiddev%d" , hdev -> minor );
1085+ dev -> hwversion = buf [2 ];
10331086 init_waitqueue_head (& dev -> wait );
10341087
10351088 hid_device_io_start (hdev );
0 commit comments