55 | 55 |
{
|
56 | 56 |
int ret = 0;
|
57 | 57 |
unsigned char outer_addr = (unsigned char)(client->addr << 1);
|
58 | |
unsigned xor = outer_addr; /* initial xor value */
|
|
58 |
unsigned xor = outer_addr; /* initial xor value */
|
59 | 59 |
|
60 | 60 |
/* Consistency checks */
|
61 | 61 |
if (len > 127)
|
|
64 | 64 |
/* Special case: sender to 0x6E is always 0x51 */
|
65 | 65 |
if (addr == DDCCI_DEFAULT_DEVICE_ADDR) {
|
66 | 66 |
addr = DDCCI_HOST_ADDR_ODD;
|
67 | |
}
|
68 | |
else {
|
|
67 |
} else {
|
69 | 68 |
/* When sending the odd address is used */
|
70 | 69 |
addr = addr | 1;
|
71 | 70 |
}
|
|
112 | 111 |
/* Special case: sender to 0x6E is always 0x51 */
|
113 | 112 |
if (addr == DDCCI_DEFAULT_DEVICE_ADDR) {
|
114 | 113 |
addr = DDCCI_HOST_ADDR_ODD;
|
115 | |
}
|
116 | |
else {
|
|
114 |
} else {
|
117 | 115 |
/* When sending the odd address is used */
|
118 | 116 |
addr = addr | 1;
|
119 | 117 |
}
|
|
339 | 337 |
*
|
340 | 338 |
* Also detects all communication quirks and sets the corresponding flags
|
341 | 339 |
* in the ddcci_bus_drv_data structure associated with client.
|
|
340 |
*
|
|
341 |
* The identification command will fail on most DDC devices, as it is optional
|
|
342 |
* to support, but even the "failed" response suffices to detect quirks.
|
342 | 343 |
*/
|
343 | 344 |
static int ddcci_identify_device(struct i2c_client* client, unsigned char addr,
|
344 | 345 |
unsigned char *buf, unsigned char len)
|
|
361 | 362 |
&& i2c_check_functionality(client->adapter,
|
362 | 363 |
I2C_FUNC_SMBUS_WRITE_BYTE)) {
|
363 | 364 |
quirks |= DDCCI_QUIRK_WRITE_BYTEWISE;
|
364 | |
dev_dbg(&client->dev, "DDC/CI bus quirk detected: writes must be done bytewise\n");
|
|
365 |
dev_dbg(&client->dev,
|
|
366 |
"DDC/CI bus quirk detected: writes must be done bytewise\n");
|
365 | 367 |
/* Some devices need writing twice after a failed blockwise write */
|
366 | 368 |
__ddcci_write_bytewise(client, addr, true, cmd, 2);
|
367 | 369 |
msleep(delay);
|
|
401 | 403 |
if (!(quirks & DDCCI_QUIRK_SKIP_FIRST_BYTE)) {
|
402 | 404 |
if (buffer[0] == buffer[1]) {
|
403 | 405 |
quirks |= DDCCI_QUIRK_SKIP_FIRST_BYTE;
|
404 | |
dev_dbg(&client->dev, "DDC/CI bus quirk detected: doubled first byte on read\n");
|
|
406 |
dev_dbg(&client->dev,
|
|
407 |
"DDC/CI bus quirk detected: doubled first byte on read\n");
|
405 | 408 |
ret--;
|
406 | 409 |
buffer++;
|
407 | 410 |
if (ret < 3) {
|
|
412 | 415 |
|
413 | 416 |
/* validate second byte (protocol flag) */
|
414 | 417 |
if ((buffer[1] & 0x80) != 0x80 && !(quirks & DDCCI_QUIRK_NO_PFLAG)) {
|
415 | |
dev_dbg(&client->dev, "DDC/CI bus quirk detected: device omits protocol flag on responses\n");
|
|
418 |
dev_dbg(&client->dev,
|
|
419 |
"DDC/CI bus quirk detected: device omits protocol flag on responses\n");
|
416 | 420 |
quirks |= DDCCI_QUIRK_NO_PFLAG;
|
417 | 421 |
}
|
418 | 422 |
|
|
429 | 433 |
|
430 | 434 |
/* verify checksum */
|
431 | 435 |
if (xor != 0) {
|
432 | |
dev_err(&client->dev, "invalid DDC/CI response, corrupted data - xor is 0x%02x, length 0x%02x\n",
|
|
436 |
dev_err(&client->dev,
|
|
437 |
"invalid DDC/CI response, corrupted data - xor is 0x%02x, length 0x%02x\n",
|
433 | 438 |
xor, payload_len);
|
434 | 439 |
return -EBADMSG;
|
435 | 440 |
}
|
|
445 | 450 |
|
446 | 451 |
/* Character device */
|
447 | 452 |
|
|
453 |
/* Data structure for an open file handle */
|
448 | 454 |
struct ddcci_fp_data {
|
449 | 455 |
struct ddcci_device *dev;
|
450 | 456 |
bool exclusive;
|
451 | 457 |
unsigned char buffer[129];
|
452 | 458 |
};
|
453 | 459 |
|
|
460 |
/* Called when the character device is opened */
|
454 | 461 |
static int ddcci_cdev_open(struct inode* inode, struct file* filp)
|
455 | 462 |
{
|
456 | 463 |
struct ddcci_device *dev = container_of(inode->i_cdev,
|
|
483 | 490 |
return 0;
|
484 | 491 |
}
|
485 | 492 |
|
|
493 |
/* Called when the character device is closed */
|
486 | 494 |
static int ddcci_cdev_close(struct inode* inode, struct file* filp)
|
487 | 495 |
{
|
488 | 496 |
struct ddcci_fp_data *fp_data = filp->private_data;
|
|
499 | 507 |
return 0;
|
500 | 508 |
}
|
501 | 509 |
|
|
510 |
/* Called when reading from the character device */
|
502 | 511 |
static ssize_t ddcci_cdev_read(struct file* filp, char __user *buffer,
|
503 | 512 |
size_t length, loff_t* offset)
|
504 | 513 |
{
|
|
538 | 547 |
return ret;
|
539 | 548 |
}
|
540 | 549 |
|
|
550 |
/* Called when writing to the character device */
|
541 | 551 |
static ssize_t ddcci_cdev_write(struct file *filp, const char __user *buffer,
|
542 | 552 |
size_t count, loff_t *offset)
|
543 | 553 |
{
|
|
587 | 597 |
return ret;
|
588 | 598 |
}
|
589 | 599 |
|
|
600 |
/* Called when seeking the character device */
|
590 | 601 |
static loff_t ddcci_cdev_seek(struct file *filp, loff_t offset, int anchor)
|
591 | 602 |
{
|
592 | 603 |
return -EINVAL;
|
|
601 | 612 |
.llseek = ddcci_cdev_seek
|
602 | 613 |
};
|
603 | 614 |
|
|
615 |
/* Set up the character device for a DDC/CI device */
|
604 | 616 |
static int ddcci_setup_char_device(struct ddcci_device *device)
|
605 | 617 |
{
|
606 | 618 |
int ret = -EINVAL;
|
|
900 | 912 |
return kasprintf(GFP_KERNEL, "bus/ddcci/%d/e%02x%02x",
|
901 | 913 |
device->i2c_client->adapter->nr,
|
902 | 914 |
device->outer_addr, device->inner_addr);
|
903 | |
}
|
904 | |
else {
|
|
915 |
} else {
|
905 | 916 |
return kasprintf(GFP_KERNEL, "bus/ddcci/%d/i%02x",
|
906 | 917 |
device->i2c_client->adapter->nr,
|
907 | 918 |
device->inner_addr);
|
908 | 919 |
}
|
909 | 920 |
}
|
910 | 921 |
|
|
922 |
/* Device type for main DDC/CI devices*/
|
911 | 923 |
static struct device_type ddcci_device_type = {
|
912 | 924 |
.name = "ddcci-device",
|
913 | 925 |
.uevent = ddcci_device_uevent,
|
|
916 | 928 |
.devnode = ddcci_devnode
|
917 | 929 |
};
|
918 | 930 |
|
|
931 |
/* Device type for dependent DDC/CI devices*/
|
919 | 932 |
static struct device_type ddcci_dependent_type = {
|
920 | 933 |
.name = "ddcci-dependent-device",
|
921 | 934 |
.uevent = ddcci_device_uevent,
|
|
1069 | 1082 |
|
1070 | 1083 |
#define IS_ANY_ID(x) (((x)[0] == -1) && ((x)[7] == -1))
|
1071 | 1084 |
|
|
1085 |
/* Check if any device id in the array matches the device and return the matching id */
|
1072 | 1086 |
static const struct ddcci_device_id *ddcci_match_id(const struct ddcci_device_id *id,
|
1073 | 1087 |
const struct ddcci_device *device)
|
1074 | 1088 |
{
|
|
1164 | 1178 |
depth++;
|
1165 | 1179 |
else if (depth > 0)
|
1166 | 1180 |
depth--;
|
1167 | |
else {
|
|
1181 |
else
|
1168 | 1182 |
break;
|
1169 | |
}
|
1170 | 1183 |
ptr = end+1;
|
1171 | 1184 |
}
|
1172 | 1185 |
return end;
|
|
1196 | 1209 |
return ++ptr;
|
1197 | 1210 |
}
|
1198 | 1211 |
|
|
1212 |
/* Fill fields in device by parsing the capability string */
|
1199 | 1213 |
static int ddcci_parse_capstring(struct ddcci_device *device)
|
1200 | 1214 |
{
|
1201 | 1215 |
char *ptr = device->capabilities;
|
|
1222 | 1236 |
return 0;
|
1223 | 1237 |
}
|
1224 | 1238 |
|
|
1239 |
/* Probe for a device on an inner address and create a ddcci_device for it */
|
1225 | 1240 |
static int ddcci_detect_device(struct i2c_client *client, unsigned char addr,
|
1226 | 1241 |
int dependent)
|
1227 | 1242 |
{
|
|
1336 | 1351 |
return ret;
|
1337 | 1352 |
}
|
1338 | 1353 |
|
|
1354 |
/* I2C detect function: check if a main or external dependent device exists */
|
1339 | 1355 |
static int ddcci_detect(struct i2c_client *client, struct i2c_board_info *info)
|
1340 | 1356 |
{
|
1341 | 1357 |
int ret;
|
|
1377 | 1393 |
return -ENODEV;
|
1378 | 1394 |
}
|
1379 | 1395 |
|
1380 | |
/* check response startf with outer addr */
|
|
1396 |
/* check response starts with outer addr */
|
1381 | 1397 |
if (buf[0] != outer_addr) {
|
1382 | 1398 |
return -ENODEV;
|
1383 | 1399 |
}
|
|
1390 | 1406 |
return 0;
|
1391 | 1407 |
}
|
1392 | 1408 |
|
|
1409 |
/* I2C probe function */
|
1393 | 1410 |
static int ddcci_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
1394 | 1411 |
{
|
1395 | 1412 |
int i, ret = -ENODEV, tmp;
|
|
1408 | 1425 |
i2c_set_clientdata(client, drv_data);
|
1409 | 1426 |
|
1410 | 1427 |
if (id->driver_data == 0) {
|
1411 | |
// Core device, probe at 0x6E
|
|
1428 |
/* Core device, probe at 0x6E */
|
1412 | 1429 |
main_addr = DDCCI_DEFAULT_DEVICE_ADDR;
|
1413 | 1430 |
dev_dbg(&client->dev, "probing core device [%02x]\n",
|
1414 | 1431 |
client->addr << 1);
|
|
1420 | 1437 |
goto err_free;
|
1421 | 1438 |
}
|
1422 | 1439 |
|
1423 | |
// Detect internal dependent devices
|
|
1440 |
/* Detect internal dependent devices */
|
1424 | 1441 |
dev_dbg(&client->dev, "probing internal dependent devices\n");
|
1425 | 1442 |
for (i = 0; i < autoprobe_addr_count; ++i) {
|
1426 | 1443 |
addr = (unsigned short)autoprobe_addrs[i];
|
|
1432 | 1449 |
}
|
1433 | 1450 |
}
|
1434 | 1451 |
}
|
1435 | |
}
|
1436 | |
else if (id->driver_data == 1) {
|
|
1452 |
} else if (id->driver_data == 1) {
|
|
1453 |
/* External dependent device */
|
1437 | 1454 |
main_addr = client->addr << 1;
|
1438 | 1455 |
dev_dbg(&client->dev, "probing external dependent device [%02x]\n", main_addr);
|
1439 | 1456 |
if ((ret = ddcci_detect_device(client, main_addr, -1))) {
|
|
1443 | 1460 |
ret = -ENODEV;
|
1444 | 1461 |
goto err_free;
|
1445 | 1462 |
}
|
1446 | |
}
|
1447 | |
else {
|
1448 | |
dev_warn(&client->dev, "probe() called with invalid i2c device id\n");
|
|
1463 |
} else {
|
|
1464 |
dev_warn(&client->dev,
|
|
1465 |
"probe() called with invalid i2c device id\n");
|
1449 | 1466 |
ret = -EINVAL;
|
1450 | 1467 |
}
|
1451 | 1468 |
|
|
1456 | 1473 |
return ret;
|
1457 | 1474 |
}
|
1458 | 1475 |
|
|
1476 |
/*
|
|
1477 |
* Callback for bus_find_device() used in ddcci_remove()
|
|
1478 |
*
|
|
1479 |
* Find next device with matching outer address not flagged with
|
|
1480 |
* DDCCI_FLAG_REMOVED and flag it.
|
|
1481 |
*/
|
1459 | 1482 |
static int ddcci_remove_helper(struct device *dev, void* p)
|
1460 | 1483 |
{
|
1461 | 1484 |
unsigned char outer_addr;
|
|
1479 | 1502 |
return 0;
|
1480 | 1503 |
}
|
1481 | 1504 |
|
|
1505 |
/* I2C driver remove callback: unregister all subdevices */
|
1482 | 1506 |
static int ddcci_remove(struct i2c_client *client)
|
1483 | 1507 |
{
|
1484 | 1508 |
struct ddcci_bus_drv_data *drv_data = i2c_get_clientdata(client);
|
|
1487 | 1511 |
|
1488 | 1512 |
down(&drv_data->sem);
|
1489 | 1513 |
while (1) {
|
1490 | |
dev = bus_find_device(&ddcci_bus_type, NULL, &outer_addr, ddcci_remove_helper);
|
|
1514 |
dev = bus_find_device(&ddcci_bus_type, NULL, &outer_addr,
|
|
1515 |
ddcci_remove_helper);
|
1491 | 1516 |
if (!dev) break;
|
1492 | 1517 |
device_unregister(dev);
|
1493 | 1518 |
put_device(dev);
|
|
1516 | 1541 |
.class = I2C_CLASS_DDC,
|
1517 | 1542 |
.detect = ddcci_detect,
|
1518 | 1543 |
.address_list = I2C_ADDRS(
|
1519 | |
DDCCI_DEFAULT_DEVICE_ADDR>>1/*,
|
1520 | |
0x08, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
|
1521 | |
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
|
1522 | |
0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x21, 0x22, 0x23,
|
1523 | |
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31,
|
1524 | |
0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39, 0x3B,
|
1525 | |
0x3C, 0x3D, 0x3E, 0x3F, 0x41, 0x42, 0x43, 0x44,
|
1526 | |
0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53,
|
1527 | |
0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x60, 0x61,
|
1528 | |
0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
|
1529 | |
0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
|
1530 | |
0x72, 0x73, 0x74, 0x75, 0x76, 0x77*/
|
|
1544 |
DDCCI_DEFAULT_DEVICE_ADDR>>1
|
1531 | 1545 |
),
|
1532 | 1546 |
};
|
1533 | 1547 |
|