@@ -156,6 +156,7 @@ struct cp2112_device {
156
156
wait_queue_head_t wait ;
157
157
u8 read_data [61 ];
158
158
u8 read_length ;
159
+ u8 hwversion ;
159
160
int xfer_status ;
160
161
atomic_t read_avail ;
161
162
atomic_t xfer_avail ;
@@ -446,33 +447,71 @@ static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data,
446
447
return data_length + 3 ;
447
448
}
448
449
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
+
449
468
static int cp2112_i2c_xfer (struct i2c_adapter * adap , struct i2c_msg * msgs ,
450
469
int num )
451
470
{
452
471
struct cp2112_device * dev = (struct cp2112_device * )adap -> algo_data ;
453
472
struct hid_device * hdev = dev -> hdev ;
454
473
u8 buf [64 ];
455
474
ssize_t count ;
475
+ ssize_t read_length = 0 ;
476
+ u8 * read_buf = NULL ;
456
477
unsigned int retries ;
457
478
int ret ;
458
479
459
480
hid_dbg (hdev , "I2C %d messages\n" , num );
460
481
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 {
462
510
hid_err (hdev ,
463
511
"Multi-message I2C transactions not supported\n" );
464
512
return - EOPNOTSUPP ;
465
513
}
466
514
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
-
476
515
ret = hid_hw_power (hdev , PM_HINT_FULLON );
477
516
if (ret < 0 ) {
478
517
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,
508
547
goto power_normal ;
509
548
}
510
549
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
+ }
521
574
}
522
575
523
- finish :
524
576
/* return the number of transferred messages */
525
- ret = 1 ;
577
+ ret = num ;
526
578
527
579
power_normal :
528
580
hid_hw_power (hdev , PM_HINT_NORMAL );
@@ -537,7 +589,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
537
589
struct cp2112_device * dev = (struct cp2112_device * )adap -> algo_data ;
538
590
struct hid_device * hdev = dev -> hdev ;
539
591
u8 buf [64 ];
540
- __be16 word ;
592
+ __le16 word ;
541
593
ssize_t count ;
542
594
size_t read_length = 0 ;
543
595
unsigned int retries ;
@@ -554,7 +606,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
554
606
if (I2C_SMBUS_READ == read_write )
555
607
count = cp2112_read_req (buf , addr , read_length );
556
608
else
557
- count = cp2112_write_req (buf , addr , data -> byte , NULL ,
609
+ count = cp2112_write_req (buf , addr , command , NULL ,
558
610
0 );
559
611
break ;
560
612
case I2C_SMBUS_BYTE_DATA :
@@ -569,7 +621,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
569
621
break ;
570
622
case I2C_SMBUS_WORD_DATA :
571
623
read_length = 2 ;
572
- word = cpu_to_be16 (data -> word );
624
+ word = cpu_to_le16 (data -> word );
573
625
574
626
if (I2C_SMBUS_READ == read_write )
575
627
count = cp2112_write_read_req (buf , addr , read_length ,
@@ -582,7 +634,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
582
634
size = I2C_SMBUS_WORD_DATA ;
583
635
read_write = I2C_SMBUS_READ ;
584
636
read_length = 2 ;
585
- word = cpu_to_be16 (data -> word );
637
+ word = cpu_to_le16 (data -> word );
586
638
587
639
count = cp2112_write_read_req (buf , addr , read_length , command ,
588
640
(u8 * )& word , 2 );
@@ -675,7 +727,7 @@ static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
675
727
data -> byte = buf [0 ];
676
728
break ;
677
729
case I2C_SMBUS_WORD_DATA :
678
- data -> word = be16_to_cpup (( __be16 * )buf );
730
+ data -> word = le16_to_cpup (( __le16 * )buf );
679
731
break ;
680
732
case I2C_SMBUS_BLOCK_DATA :
681
733
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)
1030
1082
dev -> adap .dev .parent = & hdev -> dev ;
1031
1083
snprintf (dev -> adap .name , sizeof (dev -> adap .name ),
1032
1084
"CP2112 SMBus Bridge on hiddev%d" , hdev -> minor );
1085
+ dev -> hwversion = buf [2 ];
1033
1086
init_waitqueue_head (& dev -> wait );
1034
1087
1035
1088
hid_device_io_start (hdev );
0 commit comments